internal static void SetContractFilterToIncludeAllOperations(EndpointDispatcher dispatcher, ContractDescription contract) { if (dispatcher == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("dispatcher"); } if (contract == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contract"); } if (contract.SessionMode == SessionMode.Required) { EndpointFilterProvider provider = new EndpointFilterProvider(); foreach (OperationDescription operation in contract.Operations) { if (!operation.IsServerInitiated()) { provider.InitiatingActions.Add(operation.Messages[0].Action); } } int priority; dispatcher.ContractFilter = provider.CreateFilter(out priority); dispatcher.FilterPriority = priority; } }
internal static EndpointDispatcher BuildEndpointDispatcher(ServiceDescription serviceDescription, ServiceEndpoint endpoint) { if (serviceDescription == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serviceDescription)); } var contractDescription = endpoint.Contract; if (contractDescription == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(endpoint.Contract)); } EndpointFilterProvider provider = new EndpointFilterProvider(); EndpointAddress address = endpoint.Address; EndpointDispatcher dispatcher = new EndpointDispatcher(address, contractDescription.Name, contractDescription.Namespace, endpoint.Id, endpoint.InternalIsSystemEndpoint(serviceDescription)); DispatchRuntime dispatch = dispatcher.DispatchRuntime; if (contractDescription.CallbackContractType != null) { dispatch.CallbackClientRuntime.CallbackClientType = contractDescription.CallbackContractType; dispatch.CallbackClientRuntime.ContractClientType = contractDescription.ContractType; } for (int i = 0; i < contractDescription.Operations.Count; i++) { OperationDescription operation = contractDescription.Operations[i]; if (!operation.IsServerInitiated()) { BuildDispatchOperation(operation, dispatch, provider); } else { BuildProxyOperation(operation, dispatch.CallbackClientRuntime); } } BindOperations(contractDescription, null, dispatch); //dispatcher.SetSupportedChannels(DispatcherBuilder.GetSupportedChannelTypes(contractDescription)); int filterPriority = 0; dispatcher.ContractFilter = provider.CreateFilter(out filterPriority); dispatcher.FilterPriority = filterPriority; return(dispatcher); }
static bool HaveCommonInitiatingActions(EndpointFilterProvider x, EndpointFilterProvider y, out string commonAction) { commonAction = null; foreach (string action in x.InitiatingActions) { if (y.InitiatingActions.Contains(action)) { commonAction = action; return(true); } } return(false); }
public EndpointInfo(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher, EndpointFilterProvider provider) { this.endpoint = endpoint; this.endpointDispatcher = endpointDispatcher; this.provider = provider; }
static void BuildDispatchOperation(OperationDescription operation, DispatchRuntime parent, EndpointFilterProvider provider) { string requestAction = operation.Messages[0].Action; DispatchOperation child = null; if (operation.IsOneWay) { child = new DispatchOperation(parent, operation.Name, requestAction); } else { string replyAction = operation.Messages[1].Action; child = new DispatchOperation(parent, operation.Name, requestAction, replyAction); } child.HasNoDisposableParameters = operation.HasNoDisposableParameters; child.IsTerminating = operation.IsTerminating; child.IsSessionOpenNotificationEnabled = operation.IsSessionOpenNotificationEnabled; for (int i = 0; i < operation.Faults.Count; i++) { FaultDescription fault = operation.Faults[i]; child.FaultContractInfos.Add(new FaultContractInfo(fault.Action, fault.DetailType, fault.ElementName, fault.Namespace, operation.KnownTypes)); } if (provider != null) { if (operation.IsInitiating) { provider.InitiatingActions.Add(requestAction); } } if (requestAction != MessageHeaders.WildcardAction) { parent.Operations.Add(child); } else { if (parent.HasMatchAllOperation) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.SFxMultipleContractStarOperations0)); } parent.UnhandledDispatchOperation = child; } }
internal static void InitializeServiceHost(ServiceHostBase serviceHost) { var description = serviceHost.Description; if (serviceHost.ImplementedContracts != null && serviceHost.ImplementedContracts.Count > 0) { EnsureThereAreApplicationEndpoints(description); } ValidateDescription(serviceHost); var stuffPerListenUriInfo = new Dictionary <ListenUriInfo, StuffPerListenUriInfo>(); var endpointInfosPerEndpointAddress = new Dictionary <EndpointAddress, Collection <EndpointInfo> >(); // Ensure ListenUri and group endpoints per ListenUri for (int i = 0; i < description.Endpoints.Count; i++) { ServiceEndpoint endpoint = description.Endpoints[i]; ListenUriInfo listenUriInfo = GetListenUriInfoForEndpoint(serviceHost, endpoint); if (!stuffPerListenUriInfo.ContainsKey(listenUriInfo)) { stuffPerListenUriInfo.Add(listenUriInfo, new StuffPerListenUriInfo()); } stuffPerListenUriInfo[listenUriInfo].Endpoints.Add(endpoint); } foreach (KeyValuePair <ListenUriInfo, StuffPerListenUriInfo> stuff in stuffPerListenUriInfo) { Uri listenUri = stuff.Key.ListenUri; ListenUriMode listenUriMode = stuff.Key.ListenUriMode; BindingParameterCollection parameters = stuff.Value.Parameters; Binding binding = stuff.Value.Endpoints[0].Binding; EndpointIdentity identity = stuff.Value.Endpoints[0].Address.Identity; // same EndpointAddressTable instance must be shared between channelDispatcher and parameters //ThreadSafeMessageFilterTable<EndpointAddress> endpointAddressTable = new ThreadSafeMessageFilterTable<EndpointAddress>(); //parameters.Add(endpointAddressTable); // add service-level binding parameters foreach (IServiceBehavior behavior in description.Behaviors) { behavior.AddBindingParameters(description, serviceHost, stuff.Value.Endpoints, parameters); } for (int i = 0; i < stuff.Value.Endpoints.Count; i++) { ServiceEndpoint endpoint = stuff.Value.Endpoints[i]; string viaString = listenUri.AbsoluteUri; // ensure all endpoints with this ListenUriInfo have same binding if (endpoint.Binding != binding) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.ABindingInstanceHasAlreadyBeenAssociatedTo1, viaString))); } // ensure all endpoints with this ListenUriInfo have same identity if (!object.Equals(endpoint.Address.Identity, identity)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( SR.Format(SR.SFxWhenMultipleEndpointsShareAListenUriTheyMustHaveSameIdentity, viaString))); } // add binding parameters (endpoint scope and below) AddBindingParametersForSecurityContractInformation(endpoint, parameters); AddBindingParameters(endpoint, parameters); } List <Type> channelTypes = GetSupportedChannelTypes(stuff.Value); var bindingQname = new XmlQualifiedName(binding.Name, binding.Namespace); var channelDispatcher = new ChannelDispatcher(listenUri, binding, bindingQname.ToString(), binding, channelTypes); //channelDispatcher.SetEndpointAddressTable(endpointAddressTable); stuff.Value.ChannelDispatcher = channelDispatcher; for (int i = 0; i < stuff.Value.Endpoints.Count; i++) { ServiceEndpoint endpoint = stuff.Value.Endpoints[i]; string viaString = listenUri.AbsoluteUri; //EndpointFilterProvider provider = new EndpointFilterProvider(); EndpointDispatcher dispatcher = BuildEndpointDispatcher(description, endpoint); if (!endpointInfosPerEndpointAddress.ContainsKey(endpoint.Address)) { endpointInfosPerEndpointAddress.Add(endpoint.Address, new Collection <EndpointInfo>()); } endpointInfosPerEndpointAddress[endpoint.Address].Add(new EndpointInfo(endpoint, dispatcher, /*provider*/ null)); channelDispatcher.Endpoints.Add(dispatcher); } // end foreach "endpoint" serviceHost.ChannelDispatchers.Add(channelDispatcher); } // end foreach "ListenUri/ChannelDispatcher" group // run service behaviors for (int i = 0; i < description.Behaviors.Count; i++) { IServiceBehavior serviceBehavior = description.Behaviors[i]; serviceBehavior.ApplyDispatchBehavior(description, serviceHost); } foreach (KeyValuePair <ListenUriInfo, StuffPerListenUriInfo> stuff in stuffPerListenUriInfo) { for (int i = 0; i < stuff.Value.Endpoints.Count; i++) { ServiceEndpoint endpoint = stuff.Value.Endpoints[i]; // rediscover which dispatcher goes with this endpoint Collection <EndpointInfo> infos = endpointInfosPerEndpointAddress[endpoint.Address]; EndpointInfo info = null; foreach (EndpointInfo ei in infos) { if (ei.Endpoint == endpoint) { info = ei; break; } } EndpointDispatcher dispatcher = info.EndpointDispatcher; // run contract behaviors for (int k = 0; k < endpoint.Contract.Behaviors.Count; k++) { IContractBehavior behavior = endpoint.Contract.Behaviors[k]; behavior.ApplyDispatchBehavior(endpoint.Contract, endpoint, dispatcher.DispatchRuntime); } // run endpoint behaviors ApplyBindingInformationFromEndpointToDispatcher(endpoint, dispatcher); for (int j = 0; j < endpoint.Behaviors.Count; j++) { IEndpointBehavior eb = endpoint.Behaviors[j]; eb.ApplyDispatchBehavior(endpoint, dispatcher); } // run operation behaviors BindOperations(endpoint.Contract, null, dispatcher.DispatchRuntime); } } EnsureRequiredRuntimeProperties(endpointInfosPerEndpointAddress); // Warn about obvious demux conflicts foreach (Collection <EndpointInfo> endpointInfos in endpointInfosPerEndpointAddress.Values) { // all elements of endpointInfos share the same Address (and thus EndpointListener.AddressFilter) if (endpointInfos.Count > 1) { for (int i = 0; i < endpointInfos.Count; i++) { for (int j = i + 1; j < endpointInfos.Count; j++) { // if not same ListenUri, won't conflict // if not same ChannelType, may not conflict (some transports demux based on this) // if they share a ChannelDispatcher, this means same ListenUri and same ChannelType if (endpointInfos[i].EndpointDispatcher.ChannelDispatcher == endpointInfos[j].EndpointDispatcher.ChannelDispatcher) { EndpointFilterProvider iProvider = endpointInfos[i].FilterProvider; EndpointFilterProvider jProvider = endpointInfos[j].FilterProvider; // if not default EndpointFilterProvider, we won't try to throw, you're on your own string commonAction; if (iProvider != null && jProvider != null && HaveCommonInitiatingActions(iProvider, jProvider, out commonAction)) { // you will definitely get a MultipleFiltersMatchedException at runtime, // so let's go ahead and throw now throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException( SR.Format(SR.SFxDuplicateInitiatingActionAtSameVia, endpointInfos[i].Endpoint.ListenUri, commonAction))); } } } } } } }