File: System\ServiceModel\Activation\HttpHostedTransportConfiguration.cs
Project: ndp\cdf\src\WCF\System.ServiceModel.Activation\System.ServiceModel.Activation.csproj (System.ServiceModel.Activation)
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//----------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{
    using System.Collections;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Diagnostics;
    using System.Globalization;
    using System.Net;
    using System.Security;
    using System.Runtime;
 
    class HttpHostedTransportConfiguration : HostedTransportConfigurationBase
    {
        Collection<HostedHttpTransportManager> transportManagerDirectory;
 
        internal protected HttpHostedTransportConfiguration(string scheme)
            : base(scheme)
        {
            CreateTransportManagers();
        }
 
        internal HttpHostedTransportConfiguration()
            : this(Uri.UriSchemeHttp)
        { }
 
        HostedHttpTransportManager CreateTransportManager(BaseUriWithWildcard listenAddress)
        {
            UriPrefixTable<ITransportManagerRegistration> table = null;
            if (object.ReferenceEquals(this.Scheme, Uri.UriSchemeHttp))
            {
                table = HttpChannelListener.StaticTransportManagerTable;
            }
            else
            {
                table = SharedHttpsTransportManager.StaticTransportManagerTable;
            }
 
            HostedHttpTransportManager httpManager = null;
            lock (table)
            {
                ITransportManagerRegistration registration;
                if (!table.TryLookupUri(listenAddress.BaseAddress, listenAddress.HostNameComparisonMode, out registration))
                {
                    httpManager = new HostedHttpTransportManager(listenAddress);
                    table.RegisterUri(listenAddress.BaseAddress, listenAddress.HostNameComparisonMode, httpManager);
                }
            }
 
            return httpManager;
        }
 
        void CreateTransportManagers()
        {
            Collection<HostedHttpTransportManager> tempDirectory = new Collection<HostedHttpTransportManager>();
            string[] bindings = HostedTransportConfigurationManager.MetabaseSettings.GetBindings(this.Scheme);
 
            foreach (string binding in bindings)
            {
                TryDebugPrint("HttpHostedTransportConfiguration.CreateTransportManagers() adding binding: " + binding);
                BaseUriWithWildcard listenAddress = BaseUriWithWildcard.CreateHostedUri(this.Scheme, binding, HostingEnvironmentWrapper.ApplicationVirtualPath);
 
                bool done = false;
                if (ServiceHostingEnvironment.MultipleSiteBindingsEnabled)
                {
                    //In this specific mode we only create one transport manager and all the 
                    //hosted channel listeners hang off of this transport manager
                    listenAddress = new BaseUriWithWildcard(listenAddress.BaseAddress, HostNameComparisonMode.WeakWildcard);
                    done = true;
                }
 
                HostedHttpTransportManager httpManager = CreateTransportManager(listenAddress);
 
                //httpManager will be null when 2 site bindings differ only in ip address
                if (httpManager != null)
                {
                    tempDirectory.Add(httpManager);
                    ListenAddresses.Add(listenAddress);
                }
 
                if (done)
                {
                    break;
                }
            }
 
            transportManagerDirectory = tempDirectory;
        }
 
        static bool canDebugPrint = true;
 
        [Conditional("DEBUG")]
        static void TryDebugPrint(string message)
        {
            if (canDebugPrint)
            {
                try
                {
                    Debug.Print(message);
                }
                catch (SecurityException e)
                {
                    canDebugPrint = false;
 
                    // not re-throwing on purpose
                    DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning);
                }
            }
        }
 
        internal HostedHttpTransportManager GetHttpTransportManager(Uri uri)
        {
            if (ServiceHostingEnvironment.MultipleSiteBindingsEnabled)
            {
                Fx.Assert(transportManagerDirectory.Count == 1, "There should be only one TM in this mode");
                return transportManagerDirectory[0];
            }
 
            // Optimized common cases without having to create an enumerator.
            switch (this.transportManagerDirectory.Count)
            {
                case 0:
                    return null;
 
                case 1:
                    {
                        HostedHttpTransportManager manager = this.transportManagerDirectory[0];
 
                        if (manager.Port == uri.Port &&
                            (string.Compare(manager.Scheme, uri.Scheme, StringComparison.OrdinalIgnoreCase) == 0) &&
                            (manager.HostNameComparisonMode != HostNameComparisonMode.Exact ||
                            string.Compare(manager.ListenUri.Host, uri.NormalizedHost(), StringComparison.OrdinalIgnoreCase) == 0))
                        {
                            return manager;
                        }
                        return null;
                    }
 
                default:
                    {
                        HostedHttpTransportManager foundTransportManager = null;
                        HostedHttpTransportManager weakTransportManager = null;
 
                        string scheme = uri.Scheme;
                        int port = uri.Port;
                        string host = null;
 
                        foreach (HostedHttpTransportManager manager in this.transportManagerDirectory)
                        {
                            if (manager.Port == port &&
                                string.Compare(manager.Scheme, scheme, StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                if (manager.HostNameComparisonMode == HostNameComparisonMode.StrongWildcard)
                                {
                                    return manager;
                                }
 
                                if (manager.HostNameComparisonMode == HostNameComparisonMode.WeakWildcard)
                                {
                                    weakTransportManager = manager;
                                }
 
                                if ((manager.HostNameComparisonMode == HostNameComparisonMode.Exact) &&
                                    (string.Compare(manager.Host, host ?? (host = uri.NormalizedHost()),
                                    StringComparison.OrdinalIgnoreCase) == 0))
                                {
                                    foundTransportManager = manager;
                                }
                            }
                        }
 
                        return foundTransportManager ?? weakTransportManager;
                    }
            }
        }
    }
}