TransportChannelListener.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / TransportChannelListener.cs / 1 / TransportChannelListener.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.ServiceModel.Channels 
{
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.ServiceModel;
    using System.ServiceModel.Activation; 
    using System.Diagnostics;
    using System.IO;
    using System.Runtime.Serialization;
    using System.ServiceModel.Diagnostics; 
    using System.ServiceModel.Description;
    using System.Text; 
    using System.Threading; 
    using System.Xml;
    using System.Net; 

    abstract class TransportChannelListener
        : ChannelListenerBase, ITransportFactorySettings
    { 
        static string exactGeneratedAddressPrefix;
        static string strongWildcardGeneratedAddressPrefix; 
        static string weakWildcardGeneratedAddressPrefix; 
        static object staticLock = new object();
 
        Uri baseUri;
        BufferManager bufferManager;
        HostNameComparisonMode hostNameComparisonMode;
        bool inheritBaseAddressSettings; 
        bool manualAddressing;
        long maxBufferPoolSize; 
        long maxReceivedMessageSize; 
        MessageEncoderFactory messageEncoderFactory;
        MessageVersion messageVersion; 
        Uri uri;
        string hostedVirtualPath;
        MessageReceivedCallback messageReceivedCallback;
        ServiceSecurityAuditBehavior auditBehavior; 
        ServiceModelActivity activity = null;
        TransportManagerContainer transportManagerContainer; 
 
        protected TransportChannelListener(TransportBindingElement bindingElement, BindingContext context)
            : this(bindingElement, context, TransportDefaults.GetDefaultMessageEncoderFactory()) 
        {
        }

        protected TransportChannelListener(TransportBindingElement bindingElement, BindingContext context, 
            MessageEncoderFactory defaultMessageEncoderFactory)
            : this(bindingElement, context, defaultMessageEncoderFactory, TransportDefaults.HostNameComparisonMode) 
        { 
        }
 
        protected TransportChannelListener(TransportBindingElement bindingElement, BindingContext context,
            HostNameComparisonMode hostNameComparisonMode)
            : this(bindingElement, context, TransportDefaults.GetDefaultMessageEncoderFactory(), hostNameComparisonMode)
        { 
        }
 
        protected TransportChannelListener(TransportBindingElement bindingElement, BindingContext context, 
            MessageEncoderFactory defaultMessageEncoderFactory, HostNameComparisonMode hostNameComparisonMode)
            : base(context.Binding) 
        {
            HostNameComparisonModeHelper.Validate(hostNameComparisonMode);
            this.hostNameComparisonMode = hostNameComparisonMode;
            this.manualAddressing = bindingElement.ManualAddressing; 
            this.maxBufferPoolSize = bindingElement.MaxBufferPoolSize;
            this.maxReceivedMessageSize = bindingElement.MaxReceivedMessageSize; 
 
            Collection messageEncoderBindingElements
                = context.BindingParameters.FindAll(); 

            if (messageEncoderBindingElements.Count > 1)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MultipleMebesInParameters))); 
            }
            else if (messageEncoderBindingElements.Count == 1) 
            { 
                this.messageEncoderFactory = messageEncoderBindingElements[0].CreateMessageEncoderFactory();
                context.BindingParameters.Remove(); 
            }
            else
            {
                this.messageEncoderFactory = defaultMessageEncoderFactory; 
            }
 
            if (null != this.messageEncoderFactory) 
                this.messageVersion = this.messageEncoderFactory.MessageVersion;
            else 
                this.messageVersion = MessageVersion.None;

            ServiceSecurityAuditBehavior auditBehavior = context.BindingParameters.Find();
            if (auditBehavior != null) 
            {
                this.auditBehavior = auditBehavior.Clone(); 
            } 
            else
            { 
                this.auditBehavior = new ServiceSecurityAuditBehavior();
            }

            if ((context.ListenUriMode == ListenUriMode.Unique) && (context.ListenUriBaseAddress == null)) 
            {
                UriBuilder uriBuilder = new UriBuilder(this.Scheme, DnsCache.MachineName); 
                uriBuilder.Path = this.GeneratedAddressPrefix; 
                context.ListenUriBaseAddress = uriBuilder.Uri;
            } 

            UriSchemeKeyedCollection.ValidateBaseAddress(context.ListenUriBaseAddress, "baseAddress");
            if (context.ListenUriBaseAddress.Scheme != this.Scheme)
            { 
                // URI schemes are case-insensitive, so try a case insensitive compare now
                if (string.Compare(context.ListenUriBaseAddress.Scheme, this.Scheme, StringComparison.OrdinalIgnoreCase) != 0) 
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
                        "context.ListenUriBaseAddress", 
                        SR.GetString(SR.InvalidUriScheme, context.ListenUriBaseAddress.Scheme, this.Scheme));
                }
            }
 
            DiagnosticUtility.DebugAssert(context.ListenUriRelativeAddress != null, ""); // validated by BindingContext
            if (context.ListenUriMode == ListenUriMode.Explicit) 
            { 
                this.SetUri(context.ListenUriBaseAddress, context.ListenUriRelativeAddress);
            } 
            else // ListenUriMode.Unique:
            {
                string relativeAddress = context.ListenUriRelativeAddress;
                if (relativeAddress.Length > 0 && !relativeAddress.EndsWith("/", StringComparison.Ordinal)) 
                {
                    relativeAddress += "/"; 
                } 

                this.SetUri(context.ListenUriBaseAddress, relativeAddress + Guid.NewGuid().ToString()); 
            }

            this.transportManagerContainer = new TransportManagerContainer(this);
        } 

        internal ServiceModelActivity Activity 
        { 
            get { return this.activity; }
            set { this.activity = value; } 
        }

        internal Uri BaseUri
        { 
            get
            { 
                return this.baseUri; 
            }
        } 

        string GeneratedAddressPrefix
        {
            get 
            {
                // We use different address prefixes based on hostname comparison mode in order to avoid creating 
                // starved reservations.  For example, if we register http://+:80/TLA/G1 and http://*:80/TLA/G1, the 
                // latter will never receive any traffic.  We handle this case by instead using http://+:80/TLA/G1
                // and http://*:80/TLA/G2. 
                switch (this.hostNameComparisonMode)
                {
                    case HostNameComparisonMode.Exact:
                        return GetGeneratedAddressPrefix(ref exactGeneratedAddressPrefix); 
                    case HostNameComparisonMode.StrongWildcard:
                        return GetGeneratedAddressPrefix(ref strongWildcardGeneratedAddressPrefix); 
                    case HostNameComparisonMode.WeakWildcard: 
                        return GetGeneratedAddressPrefix(ref weakWildcardGeneratedAddressPrefix);
                    default: 
                        DiagnosticUtility.DebugAssert("invalid HostnameComparisonMode value");
                        return null;
                }
            } 
        }
 
        internal string HostedVirtualPath 
        {
            get 
            {
                return this.hostedVirtualPath;
            }
        } 

        internal bool InheritBaseAddressSettings 
        { 
            get
            { 
                return this.inheritBaseAddressSettings;
            }

            set 
            {
                this.inheritBaseAddressSettings = value; 
            } 
        }
 
        internal ServiceSecurityAuditBehavior AuditBehavior
        {
            get
            { 
                return this.auditBehavior;
            } 
        } 

        public BufferManager BufferManager 
        {
            get
            {
                return this.bufferManager; 
            }
        } 
 
        internal HostNameComparisonMode HostNameComparisonModeInternal
        { 
            get
            {
                return this.hostNameComparisonMode;
            } 
        }
 
        public bool ManualAddressing 
        {
            get 
            {
                return this.manualAddressing;
            }
        } 

        public long MaxBufferPoolSize 
        { 
            get
            { 
                return this.maxBufferPoolSize;
            }
        }
 
        public virtual long MaxReceivedMessageSize
        { 
            get 
            {
                return maxReceivedMessageSize; 
            }
        }

        public MessageEncoderFactory MessageEncoderFactory 
        {
            get 
            { 
                return this.messageEncoderFactory;
            } 
        }

        public MessageVersion MessageVersion
        { 
            get
            { 
                return this.messageVersion; 
            }
        } 

        internal abstract UriPrefixTable TransportManagerTable
        {
            get; 
        }
 
        public abstract string Scheme { get; } 

        public override Uri Uri 
        {
            get
            {
                return uri; 
            }
        } 
 
        public override T GetProperty()
        { 
            if (typeof(T) == typeof(MessageVersion))
            {
                return (T)(object)this.MessageVersion;
            } 

            if (typeof(T) == typeof(FaultConverter)) 
            { 
                if (null == this.MessageEncoderFactory)
                    return null; 
                else
                    return this.MessageEncoderFactory.Encoder.GetProperty();
            }
 
            return base.GetProperty();
        } 
 
        internal bool IsScopeIdCompatible(HostNameComparisonMode hostNameComparisonMode, Uri uri)
        { 
            if (this.hostNameComparisonMode != hostNameComparisonMode)
            {
                return false;
            } 

            if (hostNameComparisonMode == HostNameComparisonMode.Exact && uri.HostNameType == UriHostNameType.IPv6) 
            { 
                // the hostname type of the channel listener MUST be IPv6 if we got here.
                // as this should have been enforced by UriPrefixTable. 
                if (this.Uri.HostNameType != UriHostNameType.IPv6)
                {
                    return false;
                } 

                IPAddress channelListenerIP = IPAddress.Parse(this.Uri.DnsSafeHost); 
                IPAddress otherIP = IPAddress.Parse(uri.DnsSafeHost); 

                if (channelListenerIP.ScopeId != otherIP.ScopeId) 
                {
                    return false;
                }
            } 

            return true; 
        } 

        internal virtual void ApplyHostedContext(VirtualPathExtension virtualPathExtension, bool isMetadataListener) 
        {
            // Save the original hosted virtual path.
            this.hostedVirtualPath = virtualPathExtension.VirtualPath;
        } 

        static Uri AddSegment(Uri baseUri, Uri fullUri) 
        { 
            Uri result = null;
            if (baseUri.AbsolutePath.Length < fullUri.AbsolutePath.Length) 
            {
                UriBuilder builder = new UriBuilder(baseUri);
                TcpChannelListener.FixIpv6Hostname(builder, baseUri);
                if (!builder.Path.EndsWith("/", StringComparison.Ordinal)) 
                {
                    builder.Path = builder.Path + "/"; 
                    baseUri = builder.Uri; 
                }
                Uri relativeUri = baseUri.MakeRelativeUri(fullUri); 
                string relativePath = relativeUri.OriginalString;
                int slashIndex = relativePath.IndexOf('/');
                string segment = (slashIndex == -1) ? relativePath : relativePath.Substring(0, slashIndex);
                builder.Path = builder.Path + segment; 
                result = builder.Uri;
            } 
            return result; 
        }
 
        internal virtual ITransportManagerRegistration CreateTransportManagerRegistration()
        {
            return this.CreateTransportManagerRegistration(this.BaseUri);
        } 

        internal abstract ITransportManagerRegistration CreateTransportManagerRegistration(Uri listenUri); 
 
        static string GetGeneratedAddressPrefix(ref string generatedAddressPrefix)
        { 
            if (generatedAddressPrefix == null)
            {
                lock (staticLock)
                { 
                    if (generatedAddressPrefix == null)
                    { 
                        // we use the ephemeral namespace prefix plus a GUID for our App-Domain (which is the 
                        // extent to which we can share a TransportManager prefix)
                        generatedAddressPrefix = "Temporary_Listen_Addresses/" + Guid.NewGuid().ToString(); 
                    }
                }
            }
            return generatedAddressPrefix; 
        }
 
        internal virtual int GetMaxBufferSize() 
        {
            if (MaxReceivedMessageSize > int.MaxValue) 
                return int.MaxValue;
            else
                return (int)MaxReceivedMessageSize;
        } 

        protected override void OnOpening() 
        { 
            base.OnOpening();
 
            // Copy the HostNameComparisonMode.
            if (HostedVirtualPath != null)
            {
                HostedTransportConfigurationBase hostedConfiguration = 
                    HostedTransportConfigurationManager.GetConfiguration(this.Scheme) as HostedTransportConfigurationBase;
                if (hostedConfiguration != null) 
                { 
                    BaseUriWithWildcard baseAddress = hostedConfiguration.FindBaseAddress(this.Uri);
                    if (baseAddress != null) 
                    {
                        this.hostNameComparisonMode = baseAddress.HostNameComparisonMode;
                    }
                    else 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.Hosting_TransportBindingNotFound, this.Uri.ToString()))); 
                    } 
                }
            } 

            this.bufferManager = BufferManager.CreateBufferManager(MaxBufferPoolSize, GetMaxBufferSize());
        }
 
        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            return this.transportManagerContainer.BeginOpen( 
                new SelectTransportManagersCallback(this.SelectTransportManagers),
                callback, state); 
        }

        protected override void OnEndOpen(IAsyncResult result)
        { 
            this.transportManagerContainer.EndOpen(result);
        } 
 
        protected override void OnOpen(TimeSpan timeout)
        { 
            this.transportManagerContainer.Open(new SelectTransportManagersCallback(this.SelectTransportManagers));
        }

        protected override void OnOpened() 
        {
            if (DiagnosticUtility.ShouldTraceVerbose) 
            { 
                TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.OpenedListener,
                    new UriTraceRecord(this.Uri), this, null); 
            }

            base.OnOpened();
        } 

        internal TransportManagerContainer GetTransportManagers() 
        { 
            return TransportManagerContainer.TransferTransportManagers(this.transportManagerContainer);
        } 

        protected override void OnAbort()
        {
            this.transportManagerContainer.Close(); 
        }
 
        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) 
        {
            return this.transportManagerContainer.BeginClose(timeout, callback, state); 
        }

        protected override void OnEndClose(IAsyncResult result)
        { 
            this.transportManagerContainer.EndClose(result);
        } 
 
        protected override void OnClose(TimeSpan timeout)
        { 
            this.transportManagerContainer.Close();
        }

        protected override void OnClosed() 
        {
            base.OnClosed(); 
            if (this.bufferManager != null) 
            {
                this.bufferManager.Clear(); 
            }
        }

        bool TryGetTransportManagerRegistration(out ITransportManagerRegistration registration) 
        {
            if (!InheritBaseAddressSettings) 
            { 
                return TryGetTransportManagerRegistration(this.hostNameComparisonMode, out registration);
            } 

            if (TryGetTransportManagerRegistration(HostNameComparisonMode.StrongWildcard, out registration))
            {
                return true; 
            }
 
            if (TryGetTransportManagerRegistration(HostNameComparisonMode.Exact, out registration)) 
            {
                return true; 
            }

            if (TryGetTransportManagerRegistration(HostNameComparisonMode.WeakWildcard, out registration))
            { 
                return true;
            } 
 
            registration = null;
            return false; 
        }

        protected virtual bool TryGetTransportManagerRegistration(HostNameComparisonMode hostNameComparisonMode,
            out ITransportManagerRegistration registration) 
        {
            return this.TransportManagerTable.TryLookupUri(this.Uri, hostNameComparisonMode, out registration); 
        } 

        // This is virtual so that PeerChannelListener and MsmqChannelListener can override it. 
        // Will be called under "lock (this.TransportManagerTable)" from TransportManagerContainer.Open
        internal virtual IList SelectTransportManagers()
        {
            IList foundTransportManagers = null; 

            // Look up an existing transport manager registration. 
            ITransportManagerRegistration registration; 
            if (!TryGetTransportManagerRegistration(out registration))
            { 
                if (DiagnosticUtility.ShouldTraceVerbose)
                {
                    TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.NoExistingTransportManager,
                        new UriTraceRecord(this.Uri), this, null); 
                }
 
                // Don't create TransportManagerRegistration in hosted case. 
                if (this.HostedVirtualPath == null)
                { 
                    // Create a new registration at the default point in the URI hierarchy.
                    registration = this.CreateTransportManagerRegistration();
                    this.TransportManagerTable.RegisterUri(registration.ListenUri, this.hostNameComparisonMode, registration);
                } 
            }
 
            // Use the registration to select/create a set of compatible transport managers. 
            if (registration != null)
            { 
                foundTransportManagers = registration.Select(this);
                if (foundTransportManagers == null)
                {
                    if (DiagnosticUtility.ShouldTraceInformation) 
                    {
                        TraceUtility.TraceEvent(TraceEventType.Information, 
                            TraceCode.IncompatibleExistingTransportManager, new UriTraceRecord(this.Uri), this, 
                            null);
                    } 

                    // Don't create TransportManagerRegistration in hosted case.
                    if (this.HostedVirtualPath == null)
                    { 
                        // Create a new registration one segment down from the existing incompatible registration.
                        Uri nextUri = AddSegment(registration.ListenUri, this.Uri); 
                        if (nextUri != null) 
                        {
                            registration = this.CreateTransportManagerRegistration(nextUri); 
                            this.TransportManagerTable.RegisterUri(nextUri, this.hostNameComparisonMode, registration);
                            foundTransportManagers = registration.Select(this);
                        }
                    } 
                }
            } 
 
            if (foundTransportManagers == null)
            { 
                ThrowTransportManagersNotFound();
            }

            return foundTransportManagers; 
        }
 
        void ThrowTransportManagersNotFound() 
        {
            if (this.HostedVirtualPath != null) 
            {
                if ((String.Compare(this.Uri.Scheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) == 0) ||
                    (String.Compare(this.Uri.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase) == 0)
                    ) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                        new InvalidOperationException( 
                            SR.GetString(SR.Hosting_NoHttpTransportManagerForUri, this.Uri)));
                } 
                else if ((String.Compare(this.Uri.Scheme, Uri.UriSchemeNetTcp, StringComparison.OrdinalIgnoreCase) == 0) ||
                         (String.Compare(this.Uri.Scheme, Uri.UriSchemeNetPipe, StringComparison.OrdinalIgnoreCase) == 0)
                         )
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new InvalidOperationException(SR.GetString( 
                            SR.Hosting_NoTcpPipeTransportManagerForUri, this.Uri))); 
                }
            } 

            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(
                    SR.NoCompatibleTransportManagerForUri, this.Uri)));
        } 

        protected void SetUri(Uri baseAddress, string relativeAddress) 
        { 
            Uri fullUri = baseAddress;
 
            // Ensure that baseAddress Path does end with a slash if we have a relative address
            if (relativeAddress != string.Empty)
            {
                if (!baseAddress.AbsolutePath.EndsWith("/", StringComparison.Ordinal)) 
                {
                    UriBuilder uriBuilder = new UriBuilder(baseAddress); 
                    TcpChannelListener.FixIpv6Hostname(uriBuilder, baseAddress); 
                    uriBuilder.Path = uriBuilder.Path + "/";
                    baseAddress = uriBuilder.Uri; 
                }

                fullUri = new Uri(baseAddress, relativeAddress);
 
                // now see if we need to update our base address (for cases like relative path = "/foo")
                if (!baseAddress.IsBaseOf(fullUri)) 
                { 
                    baseAddress = fullUri;
                } 
            }

            this.baseUri = baseAddress;
            ValidateUri(fullUri); 
            this.uri = fullUri;
        } 
 
        protected virtual void ValidateUri(Uri uri)
        { 
        }

        long ITransportFactorySettings.MaxReceivedMessageSize
        { 
            get { return MaxReceivedMessageSize; }
        } 
 
        BufferManager ITransportFactorySettings.BufferManager
        { 
            get { return BufferManager; }
        }

        bool ITransportFactorySettings.ManualAddressing 
        {
            get { return ManualAddressing; } 
        } 

        MessageEncoderFactory ITransportFactorySettings.MessageEncoderFactory 
        {
            get { return this.MessageEncoderFactory; }
        }
 
        internal void SetMessageReceivedCallback(MessageReceivedCallback messageReceivedCallback)
        { 
            this.messageReceivedCallback = messageReceivedCallback; 
        }
 
        internal void RaiseMessageReceived()
        {
            if (messageReceivedCallback != null)
            { 
                messageReceivedCallback();
            } 
        } 
    }
 
    interface ITransportManagerRegistration
    {
        HostNameComparisonMode HostNameComparisonMode { get; }
        Uri ListenUri { get; } 
        IList Select(TransportChannelListener factory);
    } 
 
    abstract class TransportManagerRegistration : ITransportManagerRegistration
    { 
        HostNameComparisonMode hostNameComparisonMode;
        Uri listenUri;

        protected TransportManagerRegistration(Uri listenUri, HostNameComparisonMode hostNameComparisonMode) 
        {
            this.listenUri = listenUri; 
            this.hostNameComparisonMode = hostNameComparisonMode; 
        }
 
        public HostNameComparisonMode HostNameComparisonMode
        {
            get { return this.hostNameComparisonMode; }
        } 

        public Uri ListenUri 
        { 
            get
            { 
                return this.listenUri;
            }
        }
 
        public abstract IList Select(TransportChannelListener factory);
    } 
 
    class UriTraceRecord : TraceRecord
    { 
        Uri uri;

        public UriTraceRecord(Uri uri)
        { 
            DiagnosticUtility.DebugAssert(uri != null, "UriTraceRecord: Uri is null");
            this.uri = uri; 
        } 

        internal override void WriteTo(XmlWriter xml) 
        {
            xml.WriteElementString("Uri", this.uri.AbsoluteUri);
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK