e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
276 lines
11 KiB
C#
276 lines
11 KiB
C#
//----------------------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//----------------------------------------------------------------------------
|
|
|
|
namespace System.ServiceModel.Activation
|
|
{
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Reflection;
|
|
using System.Runtime;
|
|
using System.Runtime.Diagnostics;
|
|
using System.Security;
|
|
using System.Security.Permissions;
|
|
using System.ServiceModel;
|
|
using System.ServiceModel.Configuration;
|
|
using System.ServiceModel.Activation.Diagnostics;
|
|
using System.ServiceModel.Diagnostics.Application;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
class HostedTransportConfigurationManager
|
|
{
|
|
IDictionary<string, HostedTransportConfiguration> configurations = new Dictionary<string, HostedTransportConfiguration>(StringComparer.Ordinal);
|
|
|
|
// Double-checked locking pattern requires volatile for read/write synchronization
|
|
volatile bool initialized = false;
|
|
MetabaseSettings metabaseSettings;
|
|
|
|
// Double-checked locking pattern requires volatile for read/write synchronization
|
|
static volatile HostedTransportConfigurationManager singleton;
|
|
static object syncRoot = new object();
|
|
#pragma warning disable 436
|
|
const string WasHostingAssemblyName = "System.ServiceModel.WasHosting, Version=" + ThisAssembly.Version + ", Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKey;
|
|
const string MetabaseSettingsIis7FactoryTypeName = "System.ServiceModel.WasHosting.MetabaseSettingsIis7Factory, " + WasHostingAssemblyName;
|
|
#pragma warning restore 436
|
|
const string CreateMetabaseSettingsIis7MethodName = "CreateMetabaseSettings";
|
|
|
|
HostedTransportConfigurationManager()
|
|
{
|
|
if (!Iis7Helper.IsIis7)
|
|
{
|
|
metabaseSettings = new MetabaseSettingsIis6();
|
|
}
|
|
else
|
|
{
|
|
|
|
metabaseSettings = CreateWasHostingMetabaseSettings();
|
|
}
|
|
}
|
|
|
|
HostedTransportConfigurationManager(MetabaseSettings metabaseSettings)
|
|
{
|
|
this.metabaseSettings = metabaseSettings;
|
|
}
|
|
|
|
[Fx.Tag.SecurityNote(Critical = "Calls Critical methods CreateMetabaseSettings.",
|
|
Safe = "Ensures that only the correct, well-known method is called to construct the metabase settings. No other " +
|
|
"details are leaked, and no control flow or data is allowed in.")]
|
|
[SecuritySafeCritical]
|
|
static MetabaseSettingsIis CreateWasHostingMetabaseSettings()
|
|
{
|
|
Type type = Type.GetType(MetabaseSettingsIis7FactoryTypeName, false);
|
|
if (type == null)
|
|
{
|
|
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_MetabaseSettingsIis7TypeNotFound(MetabaseSettingsIis7FactoryTypeName, WasHostingAssemblyName)));
|
|
}
|
|
return CreateMetabaseSettings(type);
|
|
}
|
|
|
|
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.SecureAsserts, Justification = "This is a private SecurityCritical method and its only caller passes in non-user data. Users cannot pass arbitrary data to this code.")]
|
|
[Fx.Tag.SecurityNote(Critical = "Asserts full trust in order to call a well-known internal static in WasHosting.dll." +
|
|
"Caller must ensure that 'type' argument refers to the trusted, well-known Type.")]
|
|
[SecurityCritical]
|
|
static MetabaseSettingsIis CreateMetabaseSettings(Type type)
|
|
{
|
|
object instance = null;
|
|
MethodInfo method = type.GetMethod(CreateMetabaseSettingsIis7MethodName, BindingFlags.NonPublic | BindingFlags.Static);
|
|
|
|
try
|
|
{
|
|
new PermissionSet(PermissionState.Unrestricted).Assert();
|
|
|
|
instance = method.Invoke(null, null);
|
|
}
|
|
finally
|
|
{
|
|
PermissionSet.RevertAssert();
|
|
}
|
|
|
|
if (!(instance is MetabaseSettingsIis))
|
|
{
|
|
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_BadMetabaseSettingsIis7Type(type.AssemblyQualifiedName)));
|
|
}
|
|
|
|
return (MetabaseSettingsIis)instance;
|
|
}
|
|
|
|
internal static void EnsureInitializedForSimpleApplicationHost(HostedHttpRequestAsyncResult result)
|
|
{
|
|
if (singleton != null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lock (syncRoot)
|
|
{
|
|
if (singleton != null)
|
|
return;
|
|
|
|
singleton = new HostedTransportConfigurationManager(new MetabaseSettingsCassini(result));
|
|
}
|
|
}
|
|
|
|
internal static MetabaseSettings MetabaseSettings
|
|
{
|
|
get
|
|
{
|
|
return HostedTransportConfigurationManager.Value.metabaseSettings;
|
|
}
|
|
}
|
|
|
|
object ThisLock
|
|
{
|
|
get
|
|
{
|
|
return this;
|
|
}
|
|
}
|
|
|
|
static HostedTransportConfigurationManager Value
|
|
{
|
|
get
|
|
{
|
|
if (singleton == null)
|
|
{
|
|
lock (syncRoot)
|
|
{
|
|
if (singleton == null)
|
|
{
|
|
//Ensure ETW tracing is initialized
|
|
System.ServiceModel.Diagnostics.TraceUtility.SetEtwProviderId();
|
|
|
|
if (TD.HostedTransportConfigurationManagerConfigInitStartIsEnabled())
|
|
{
|
|
TD.HostedTransportConfigurationManagerConfigInitStart();
|
|
}
|
|
ServiceHostingEnvironment.EnsureInitialized();
|
|
singleton = new HostedTransportConfigurationManager();
|
|
if (TD.HostedTransportConfigurationManagerConfigInitStopIsEnabled())
|
|
{
|
|
TD.HostedTransportConfigurationManagerConfigInitStop();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return singleton;
|
|
}
|
|
}
|
|
|
|
void EnsureInitialized()
|
|
{
|
|
if (!initialized)
|
|
{
|
|
lock (ThisLock)
|
|
{
|
|
if (!initialized)
|
|
{
|
|
// Register protocols.
|
|
foreach (string protocol in metabaseSettings.GetProtocols())
|
|
{
|
|
// special case HTTP, it's a legacy protocol
|
|
if (string.CompareOrdinal(protocol, Uri.UriSchemeHttp) == 0 ||
|
|
string.CompareOrdinal(protocol, Uri.UriSchemeHttps) == 0)
|
|
{
|
|
HttpHostedTransportConfiguration httpConfiguration = null;
|
|
if (string.CompareOrdinal(protocol, Uri.UriSchemeHttp) == 0)
|
|
{
|
|
httpConfiguration = new HttpHostedTransportConfiguration();
|
|
}
|
|
else
|
|
{
|
|
httpConfiguration = new HttpsHostedTransportConfiguration();
|
|
}
|
|
|
|
configurations.Add(protocol, httpConfiguration);
|
|
}
|
|
else
|
|
{
|
|
if (!Iis7Helper.IsIis7)
|
|
{
|
|
throw Fx.AssertAndThrowFatal("HostedTransportConfigurationManager.EnsureInitialized() protocols other than http and https can only be configured in IIS7");
|
|
}
|
|
if (AspNetPartialTrustHelpers.NeedPartialTrustInvoke)
|
|
{
|
|
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.PartialTrustNonHttpActivation(protocol, HostingEnvironmentWrapper.ApplicationVirtualPath)));
|
|
}
|
|
AddHostedTransportConfigurationIis7(protocol);
|
|
}
|
|
}
|
|
|
|
initialized = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void AddHostedTransportConfigurationIis7(string protocol)
|
|
{
|
|
HostedTransportConfiguration configuration = null;
|
|
try
|
|
{
|
|
ServiceHostingEnvironmentSection section = ServiceHostingEnvironmentSection.GetSection();
|
|
if (section.TransportConfigurationTypes.ContainsKey(protocol))
|
|
{
|
|
TransportConfigurationTypeElement element = section.TransportConfigurationTypes[protocol];
|
|
Debug.Print("HostedTransportConfigurationManager.AddHostedTransportConfigurationIis7() found TransportConfigurationTypes for protocol: " + protocol + " name: " + element.TransportConfigurationType);
|
|
|
|
Type type = Type.GetType(element.TransportConfigurationType);
|
|
configuration = Activator.CreateInstance(type) as HostedTransportConfiguration;
|
|
configurations.Add(protocol, configuration);
|
|
}
|
|
else
|
|
{
|
|
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_ProtocolNoConfiguration(protocol)));
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
if (!Fx.IsFatal(exception))
|
|
{
|
|
Debug.Print("HostedTransportConfigurationManager.AddHostedTransportConfigurationIis7() caught exception: " + exception);
|
|
if (DiagnosticUtility.ShouldTraceError)
|
|
{
|
|
TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.WebHostProtocolMisconfigured, SR.TraceCodeWebHostProtocolMisconfigured,
|
|
new StringTraceRecord("Protocol", protocol),
|
|
this, exception);
|
|
}
|
|
}
|
|
throw;
|
|
}
|
|
}
|
|
|
|
internal static Uri[] GetBaseAddresses(string virtualPath)
|
|
{
|
|
return HostedTransportConfigurationManager.Value.InternalGetBaseAddresses(virtualPath);
|
|
}
|
|
|
|
internal static HostedTransportConfiguration GetConfiguration(string scheme)
|
|
{
|
|
return HostedTransportConfigurationManager.Value.InternalGetConfiguration(scheme);
|
|
}
|
|
|
|
Uri[] InternalGetBaseAddresses(string virtualPath)
|
|
{
|
|
EnsureInitialized();
|
|
List<Uri> baseAddresses = new List<Uri>();
|
|
foreach (HostedTransportConfiguration configuration in configurations.Values)
|
|
{
|
|
baseAddresses.AddRange(configuration.GetBaseAddresses(virtualPath));
|
|
}
|
|
|
|
return baseAddresses.ToArray();
|
|
}
|
|
|
|
HostedTransportConfiguration InternalGetConfiguration(string scheme)
|
|
{
|
|
EnsureInitialized();
|
|
if (!configurations.ContainsKey(scheme))
|
|
{
|
|
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_NotSupportedProtocol(scheme)));
|
|
}
|
|
|
|
return configurations[scheme];
|
|
}
|
|
}
|
|
}
|