| File: FrameworkFork\System.ServiceModel\System\ServiceModel\Channels\ReliableSessionBindingElement.cs | Web Access |
| Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. namespace System.ServiceModel.Channels { using System.ComponentModel; using System.Runtime; using System.ServiceModel; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; using System.ServiceModel.Security; using Microsoft.Xml; public sealed class ReliableSessionBindingElement : BindingElement, IPolicyExportExtension { private TimeSpan _acknowledgementInterval = ReliableSessionDefaults.AcknowledgementInterval; private bool _flowControlEnabled = ReliableSessionDefaults.FlowControlEnabled; private TimeSpan _inactivityTimeout = ReliableSessionDefaults.InactivityTimeout; private int _maxPendingChannels = ReliableSessionDefaults.MaxPendingChannels; private int _maxRetryCount = ReliableSessionDefaults.MaxRetryCount; private int _maxTransferWindowSize = ReliableSessionDefaults.MaxTransferWindowSize; private bool _ordered = ReliableSessionDefaults.Ordered; private ReliableMessagingVersion _reliableMessagingVersion = ReliableMessagingVersion.Default; private static MessagePartSpecification s_bodyOnly; public ReliableSessionBindingElement() { } internal ReliableSessionBindingElement(ReliableSessionBindingElement elementToBeCloned) : base(elementToBeCloned) { this.AcknowledgementInterval = elementToBeCloned.AcknowledgementInterval; this.FlowControlEnabled = elementToBeCloned.FlowControlEnabled; this.InactivityTimeout = elementToBeCloned.InactivityTimeout; this.MaxPendingChannels = elementToBeCloned.MaxPendingChannels; this.MaxRetryCount = elementToBeCloned.MaxRetryCount; this.MaxTransferWindowSize = elementToBeCloned.MaxTransferWindowSize; this.Ordered = elementToBeCloned.Ordered; this.ReliableMessagingVersion = elementToBeCloned.ReliableMessagingVersion; } public ReliableSessionBindingElement(bool ordered) { _ordered = ordered; } [DefaultValue(typeof(TimeSpan), ReliableSessionDefaults.AcknowledgementIntervalString)] public TimeSpan AcknowledgementInterval { get { return _acknowledgementInterval; } set { if (value <= TimeSpan.Zero) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, SRServiceModel.TimeSpanMustbeGreaterThanTimeSpanZero)); } if (TimeoutHelper.IsTooLarge(value)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, SRServiceModel.SFxTimeoutOutOfRangeTooBig)); } _acknowledgementInterval = value; } } [DefaultValue(ReliableSessionDefaults.FlowControlEnabled)] public bool FlowControlEnabled { get { return _flowControlEnabled; } set { _flowControlEnabled = value; } } [DefaultValue(typeof(TimeSpan), ReliableSessionDefaults.InactivityTimeoutString)] public TimeSpan InactivityTimeout { get { return _inactivityTimeout; } set { if (value <= TimeSpan.Zero) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, SRServiceModel.TimeSpanMustbeGreaterThanTimeSpanZero)); } if (TimeoutHelper.IsTooLarge(value)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, SRServiceModel.SFxTimeoutOutOfRangeTooBig)); } _inactivityTimeout = value; } } [DefaultValue(ReliableSessionDefaults.MaxPendingChannels)] public int MaxPendingChannels { get { return _maxPendingChannels; } set { if (value <= 0 || value > 16384) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, string.Format(SRServiceModel.ValueMustBeInRange, 0, 16384))); _maxPendingChannels = value; } } [DefaultValue(ReliableSessionDefaults.MaxRetryCount)] public int MaxRetryCount { get { return _maxRetryCount; } set { if (value <= 0) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, SRServiceModel.ValueMustBePositive)); _maxRetryCount = value; } } [DefaultValue(ReliableSessionDefaults.MaxTransferWindowSize)] public int MaxTransferWindowSize { get { return _maxTransferWindowSize; } set { if (value <= 0 || value > 4096) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, string.Format(SRServiceModel.ValueMustBeInRange, 0, 4096))); _maxTransferWindowSize = value; } } [DefaultValue(ReliableSessionDefaults.Ordered)] public bool Ordered { get { return _ordered; } set { _ordered = value; } } [DefaultValue(typeof(ReliableMessagingVersion), ReliableSessionDefaults.ReliableMessagingVersionString)] public ReliableMessagingVersion ReliableMessagingVersion { get { return _reliableMessagingVersion; } set { if (value == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value"); } if (!ReliableMessagingVersion.IsDefined(value)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value")); } _reliableMessagingVersion = value; } } private static MessagePartSpecification BodyOnly { get { if (s_bodyOnly == null) { MessagePartSpecification temp = new MessagePartSpecification(true); temp.MakeReadOnly(); s_bodyOnly = temp; } return s_bodyOnly; } } public override BindingElement Clone() { return new ReliableSessionBindingElement(this); } public override T GetProperty<T>(BindingContext context) { throw new NotImplementedException(); } public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context) { throw new NotImplementedException(); } public override bool CanBuildChannelFactory<TChannel>(BindingContext context) { throw new NotImplementedException(); } internal override bool IsMatch(BindingElement b) { if (b == null) return false; ReliableSessionBindingElement session = b as ReliableSessionBindingElement; if (session == null) return false; if (_acknowledgementInterval != session._acknowledgementInterval) return false; if (_flowControlEnabled != session._flowControlEnabled) return false; if (_inactivityTimeout != session._inactivityTimeout) return false; if (_maxPendingChannels != session._maxPendingChannels) return false; if (_maxRetryCount != session._maxRetryCount) return false; if (_maxTransferWindowSize != session._maxTransferWindowSize) return false; if (_ordered != session._ordered) return false; if (_reliableMessagingVersion != session._reliableMessagingVersion) return false; return true; } private static void ProtectProtocolMessage( ScopedMessagePartSpecification signaturePart, ScopedMessagePartSpecification encryptionPart, string action) { signaturePart.AddParts(BodyOnly, action); encryptionPart.AddParts(MessagePartSpecification.NoParts, action); //encryptionPart.AddParts(BodyOnly, action); } private void SetSecuritySettings(BindingContext context) { SecurityBindingElement element = context.RemainingBindingElements.Find<SecurityBindingElement>(); if (element != null) { element.LocalServiceSettings.ReconnectTransportOnFailure = true; } } private void VerifyTransportMode(BindingContext context) { TransportBindingElement transportElement = context.RemainingBindingElements.Find<TransportBindingElement>(); // Verify ManualAdderssing is turned off. if ((transportElement != null) && (transportElement.ManualAddressing)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(SRServiceModel.ManualAddressingNotSupported)); } ConnectionOrientedTransportBindingElement connectionElement = transportElement as ConnectionOrientedTransportBindingElement; HttpTransportBindingElement httpElement = transportElement as HttpTransportBindingElement; // Verify TransportMode is Buffered. TransferMode transportTransferMode; if (connectionElement != null) { transportTransferMode = connectionElement.TransferMode; } else if (httpElement != null) { transportTransferMode = httpElement.TransferMode; } else { // Not one of the elements we can check, we have to assume TransferMode.Buffered. transportTransferMode = TransferMode.Buffered; } if (transportTransferMode != TransferMode.Buffered) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException(string.Format(SRServiceModel.TransferModeNotSupported, transportTransferMode, this.GetType().Name))); } } void IPolicyExportExtension.ExportPolicy(MetadataExporter exporter, PolicyConversionContext context) { if (exporter == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context"); if (context == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context"); if (context.BindingElements != null) { BindingElementCollection bindingElements = context.BindingElements; ReliableSessionBindingElement settings = bindingElements.Find<ReliableSessionBindingElement>(); if (settings != null) { // ReliableSession assertion XmlElement assertion = settings.CreateReliabilityAssertion(exporter.PolicyVersion, bindingElements); context.GetBindingAssertions().Add(assertion); } } } private static XmlElement CreatePolicyElement(PolicyVersion policyVersion, XmlDocument doc) { string policy = MetadataStrings.WSPolicy.Elements.Policy; string policyNs = policyVersion.Namespace; string policyPrefix = MetadataStrings.WSPolicy.Prefix; return doc.CreateElement(policyPrefix, policy, policyNs); } private XmlElement CreateReliabilityAssertion(PolicyVersion policyVersion, BindingElementCollection bindingElements) { XmlDocument doc = new XmlDocument(); XmlElement child = null; string reliableSessionPrefix; string reliableSessionNs; string assertionPrefix; string assertionNs; if (this.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005) { reliableSessionPrefix = ReliableSessionPolicyStrings.ReliableSessionFebruary2005Prefix; reliableSessionNs = ReliableSessionPolicyStrings.ReliableSessionFebruary2005Namespace; assertionPrefix = reliableSessionPrefix; assertionNs = reliableSessionNs; } else { reliableSessionPrefix = ReliableSessionPolicyStrings.ReliableSession11Prefix; reliableSessionNs = ReliableSessionPolicyStrings.ReliableSession11Namespace; assertionPrefix = ReliableSessionPolicyStrings.NET11Prefix; assertionNs = ReliableSessionPolicyStrings.NET11Namespace; } // ReliableSession assertion XmlElement assertion = doc.CreateElement(reliableSessionPrefix, ReliableSessionPolicyStrings.ReliableSessionName, reliableSessionNs); if (this.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11) { // Policy XmlElement policy = CreatePolicyElement(policyVersion, doc); // SequenceSTR if (IsSecureConversationEnabled(bindingElements)) { XmlElement sequenceSTR = doc.CreateElement(reliableSessionPrefix, ReliableSessionPolicyStrings.SequenceSTR, reliableSessionNs); policy.AppendChild(sequenceSTR); } // DeliveryAssurance XmlElement deliveryAssurance = doc.CreateElement(reliableSessionPrefix, ReliableSessionPolicyStrings.DeliveryAssurance, reliableSessionNs); // Policy XmlElement nestedPolicy = CreatePolicyElement(policyVersion, doc); // ExactlyOnce XmlElement exactlyOnce = doc.CreateElement(reliableSessionPrefix, ReliableSessionPolicyStrings.ExactlyOnce, reliableSessionNs); nestedPolicy.AppendChild(exactlyOnce); if (_ordered) { // InOrder XmlElement inOrder = doc.CreateElement(reliableSessionPrefix, ReliableSessionPolicyStrings.InOrder, reliableSessionNs); nestedPolicy.AppendChild(inOrder); } deliveryAssurance.AppendChild(nestedPolicy); policy.AppendChild(deliveryAssurance); assertion.AppendChild(policy); } // Nested InactivityTimeout assertion child = doc.CreateElement(assertionPrefix, ReliableSessionPolicyStrings.InactivityTimeout, assertionNs); WriteMillisecondsAttribute(child, this.InactivityTimeout); assertion.AppendChild(child); // Nested AcknowledgementInterval assertion child = doc.CreateElement(assertionPrefix, ReliableSessionPolicyStrings.AcknowledgementInterval, assertionNs); WriteMillisecondsAttribute(child, this.AcknowledgementInterval); assertion.AppendChild(child); return assertion; } private static bool IsSecureConversationEnabled(BindingElementCollection bindingElements) { bool foundRM = false; for (int i = 0; i < bindingElements.Count; i++) { if (!foundRM) { ReliableSessionBindingElement bindingElement = bindingElements[i] as ReliableSessionBindingElement; foundRM = (bindingElement != null); } else { SecurityBindingElement securityBindingElement = bindingElements[i] as SecurityBindingElement; if (securityBindingElement != null) { SecurityBindingElement bootstrapSecurity; // The difference in bool (requireCancellation) does not affect whether the binding is valid, // but the method does match on the value so we need to pass both true and false. return SecurityBindingElement.IsSecureConversationBinding(securityBindingElement, true, out bootstrapSecurity) || SecurityBindingElement.IsSecureConversationBinding(securityBindingElement, false, out bootstrapSecurity); } break; } } return false; } private static void WriteMillisecondsAttribute(XmlElement childElement, TimeSpan timeSpan) { UInt64 milliseconds = Convert.ToUInt64(timeSpan.TotalMilliseconds); childElement.SetAttribute(ReliableSessionPolicyStrings.Milliseconds, XmlConvert.ToString(milliseconds)); } private class BindingDeliveryCapabilitiesHelper : IBindingDeliveryCapabilities { private ReliableSessionBindingElement _element; private IBindingDeliveryCapabilities _inner; internal BindingDeliveryCapabilitiesHelper(ReliableSessionBindingElement element, IBindingDeliveryCapabilities inner) { _element = element; _inner = inner; } bool IBindingDeliveryCapabilities.AssuresOrderedDelivery { get { return _element.Ordered; } } bool IBindingDeliveryCapabilities.QueuedDelivery { get { return _inner != null ? _inner.QueuedDelivery : false; } } } } }