//----------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.ServiceModel.Dispatcher { using System; using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Diagnostics; public class EndpointDispatcher { MessageFilter addressFilter; bool addressFilterSetExplicit; ChannelDispatcher channelDispatcher; MessageFilter contractFilter; string contractName; string contractNamespace; ServiceChannel datagramChannel; DispatchRuntime dispatchRuntime; MessageFilter endpointFilter; int filterPriority; Uri listenUri; EndpointAddress originalAddress; string perfCounterId; string perfCounterBaseId; string id; // for ServiceMetadataBehavior, to help get EndpointIdentity of ServiceEndpoint from EndpointDispatcher bool isSystemEndpoint; internal EndpointDispatcher(EndpointAddress address, string contractName, string contractNamespace, string id, bool isSystemEndpoint) : this(address, contractName, contractNamespace) { this.id = id; this.isSystemEndpoint = isSystemEndpoint; } public EndpointDispatcher(EndpointAddress address, string contractName, string contractNamespace) : this(address, contractName, contractNamespace, false) { } public EndpointDispatcher(EndpointAddress address, string contractName, string contractNamespace, bool isSystemEndpoint) { this.originalAddress = address; this.contractName = contractName; this.contractNamespace = contractNamespace; if (address != null) { this.addressFilter = new EndpointAddressMessageFilter(address); } else { this.addressFilter = new MatchAllMessageFilter(); } this.contractFilter = new MatchAllMessageFilter(); this.dispatchRuntime = new DispatchRuntime(this); this.filterPriority = 0; this.isSystemEndpoint = isSystemEndpoint; } EndpointDispatcher(EndpointDispatcher baseEndpoint, IEnumerable headers) { EndpointAddressBuilder builder = new EndpointAddressBuilder(baseEndpoint.EndpointAddress); foreach (AddressHeader h in headers) { builder.Headers.Add(h); } EndpointAddress address = builder.ToEndpointAddress(); this.addressFilter = new EndpointAddressMessageFilter(address); // channelDispatcher is Attached this.contractFilter = baseEndpoint.ContractFilter; this.contractName = baseEndpoint.ContractName; this.contractNamespace = baseEndpoint.ContractNamespace; this.dispatchRuntime = baseEndpoint.DispatchRuntime; // endpointFilter is lazy this.filterPriority = baseEndpoint.FilterPriority + 1; this.originalAddress = address; if (PerformanceCounters.PerformanceCountersEnabled) { this.perfCounterId = baseEndpoint.perfCounterId; this.perfCounterBaseId = baseEndpoint.perfCounterBaseId; } this.id = baseEndpoint.id; } public MessageFilter AddressFilter { get { return this.addressFilter; } set { if (value == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value"); } this.ThrowIfDisposedOrImmutable(); this.addressFilter = value; this.addressFilterSetExplicit = true; } } internal bool AddressFilterSetExplicit { get { return this.addressFilterSetExplicit; } } public ChannelDispatcher ChannelDispatcher { get { return this.channelDispatcher; } } public MessageFilter ContractFilter { get { return this.contractFilter; } set { if (value == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value"); } this.ThrowIfDisposedOrImmutable(); this.contractFilter = value; } } public string ContractName { get { return this.contractName; } } public string ContractNamespace { get { return this.contractNamespace; } } internal ServiceChannel DatagramChannel { get { return this.datagramChannel; } set { this.datagramChannel = value; } } public DispatchRuntime DispatchRuntime { get { return this.dispatchRuntime; } } internal Uri ListenUri { get { return this.listenUri; } } internal EndpointAddress OriginalAddress { get { return this.originalAddress; } } public EndpointAddress EndpointAddress { get { if (this.channelDispatcher == null) { return this.originalAddress; } if ((this.originalAddress != null) && (this.originalAddress.Identity != null)) { return this.originalAddress; } IChannelListener listener = this.channelDispatcher.Listener; EndpointIdentity identity = listener.GetProperty(); if ((this.originalAddress != null) && (identity == null)) { return this.originalAddress; } EndpointAddressBuilder builder; if (this.originalAddress != null) { builder = new EndpointAddressBuilder(this.originalAddress); } else { builder = new EndpointAddressBuilder(); builder.Uri = listener.Uri; } builder.Identity = identity; return builder.ToEndpointAddress(); } } public bool IsSystemEndpoint { get { return this.isSystemEndpoint; } } internal MessageFilter EndpointFilter { get { if (this.endpointFilter == null) { MessageFilter addressFilter = this.addressFilter; MessageFilter contractFilter = this.contractFilter; // Can't optimize addressFilter similarly. // AndMessageFilter tracks when the address filter matched so the correct // fault can be sent back. if (contractFilter is MatchAllMessageFilter) { this.endpointFilter = addressFilter; } else { this.endpointFilter = new AndMessageFilter(addressFilter, contractFilter); } } return this.endpointFilter; } } public int FilterPriority { get { return this.filterPriority; } set { this.filterPriority = value; } } internal string Id { get { return this.id; } set { this.id = value; } } internal string PerfCounterId { get { return this.perfCounterId; } } internal string PerfCounterBaseId { get { return this.perfCounterBaseId; } } internal int PerfCounterInstanceId { get; set; } static internal EndpointDispatcher AddEndpointDispatcher(EndpointDispatcher baseEndpoint, IEnumerable headers) { EndpointDispatcher endpoint = new EndpointDispatcher(baseEndpoint, headers); baseEndpoint.ChannelDispatcher.Endpoints.Add(endpoint); return endpoint; } internal void Attach(ChannelDispatcher channelDispatcher) { if (channelDispatcher == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("channelDispatcher"); } if (this.channelDispatcher != null) { Exception error = new InvalidOperationException(SR.GetString(SR.SFxEndpointDispatcherMultipleChannelDispatcher0)); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error); } this.channelDispatcher = channelDispatcher; this.listenUri = channelDispatcher.Listener.Uri; } internal void Detach(ChannelDispatcher channelDispatcher) { if (channelDispatcher == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("channelDispatcher"); } if (this.channelDispatcher != channelDispatcher) { Exception error = new InvalidOperationException(SR.GetString(SR.SFxEndpointDispatcherDifferentChannelDispatcher0)); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error); } this.ReleasePerformanceCounters(); this.channelDispatcher = null; } internal void ReleasePerformanceCounters() { if (PerformanceCounters.PerformanceCountersEnabled) { PerformanceCounters.ReleasePerformanceCountersForEndpoint(this.perfCounterId, this.perfCounterBaseId); } } internal bool SetPerfCounterId() { Uri keyUri = null; if (null != this.ListenUri) { keyUri = this.ListenUri; } else { EndpointAddress endpointAddress = this.EndpointAddress; if (null != endpointAddress) { keyUri = endpointAddress.Uri; } } if (null != keyUri) { this.perfCounterBaseId = keyUri.AbsoluteUri.ToUpperInvariant(); this.perfCounterId = this.perfCounterBaseId + "/" + contractName.ToUpperInvariant(); return true; } else { return false; } } void ThrowIfDisposedOrImmutable() { ChannelDispatcher channelDispatcher = this.channelDispatcher; if (channelDispatcher != null) { channelDispatcher.ThrowIfDisposedOrImmutable(); } } } }