< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Description.DispatcherBuilder
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Description/DispatcherBuilder.cs
Line coverage
86%
Covered lines: 356
Uncovered lines: 54
Coverable lines: 410
Total lines: 911
Line coverage: 86.8%
Branch coverage
80%
Covered branches: 204
Total branches: 254
Branch coverage: 80.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Description/DispatcherBuilder.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.Collections.ObjectModel;
 7using System.Linq;
 8using System.Reflection;
 9using System.Threading.Tasks;
 10using System.Xml;
 11using CoreWCF.Channels;
 12using CoreWCF.Configuration;
 13using CoreWCF.Dispatcher;
 14using CoreWCF.Runtime;
 15using CoreWCF.Security;
 16using Microsoft.AspNetCore.Authorization;
 17using Microsoft.AspNetCore.Hosting.Server.Features;
 18using Microsoft.Extensions.DependencyInjection;
 19
 20namespace CoreWCF.Description
 21{
 22    internal class DispatcherBuilder
 23    {
 24        private static void ValidateDescription(ServiceHostBase serviceHost)
 25        {
 57626            ServiceDescription description = serviceHost.Description;
 57627            description.EnsureInvariants();
 28            // TODO: Reenable SecurityValidationBehavior validation
 29            //(SecurityValidationBehavior.Instance as IServiceBehavior).Validate(description, serviceHost);
 57630            (new UniqueContractNameValidationBehavior() as IServiceBehavior).Validate(description, serviceHost);
 485031            for (int i = 0; i < description.Behaviors.Count; i++)
 32            {
 184933                IServiceBehavior iServiceBehavior = description.Behaviors[i];
 184934                iServiceBehavior.Validate(description, serviceHost);
 35            }
 243436            for (int i = 0; i < description.Endpoints.Count; i++)
 37            {
 64138                ServiceEndpoint endpoint = description.Endpoints[i];
 64139                ContractDescription contract = endpoint.Contract;
 64140                bool alreadyProcessedThisContract = false;
 128441                for (int j = 0; j < i; j++)
 42                {
 6543                    if (description.Endpoints[j].Contract == contract)
 44                    {
 6445                        alreadyProcessedThisContract = true;
 6446                        break;
 47                    }
 48                }
 64149                endpoint.ValidateForService(!alreadyProcessedThisContract);
 50            }
 57651        }
 52
 53        private static void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection parameters)
 54        {
 257655            foreach (IContractBehavior icb in endpoint.Contract.Behaviors)
 56            {
 64757                icb.AddBindingParameters(endpoint.Contract, endpoint, parameters);
 58            }
 272059            foreach (IEndpointBehavior ieb in endpoint.Behaviors)
 60            {
 71961                ieb.AddBindingParameters(endpoint, parameters);
 62            }
 733863            foreach (OperationDescription op in endpoint.Contract.Operations)
 64            {
 2458265                foreach (IOperationBehavior iob in op.Behaviors)
 66                {
 926367                    iob.AddBindingParameters(op, parameters);
 68                }
 69            }
 64170        }
 71
 72        private static void EnsureThereAreApplicationEndpoints(ServiceDescription description)
 73        {
 172874            foreach (ServiceEndpoint endpoint in description.Endpoints)
 75            {
 57676                if (!endpoint.InternalIsSystemEndpoint(description))
 77                {
 57678                    return;
 79                }
 80            }
 081            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
 082                                                                          SR.Format(SR.ServiceHasZeroAppEndpoints, descr
 57683        }
 84
 85        internal static Uri EnsureListenUri(ServiceHostBase serviceHost, ServiceEndpoint endpoint)
 86        {
 64187            Uri listenUri = endpoint.ListenUri;
 64188            if (listenUri == null)
 89            {
 90                // TODO: Make sure the InternalBaseAddresses are populated with the relevant base address for the transp
 091                listenUri = GetVia(endpoint.Binding.Scheme, ServiceHostBase.s_emptyUri, serviceHost.InternalBaseAddresse
 92            }
 64193            if (listenUri == null)
 94            {
 95                // TODO: Plumb through expected scheme and update exception message
 096                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.SFx
 97            }
 64198            return listenUri;
 99        }
 100
 101        internal static Uri GetVia(string scheme, Uri address, UriSchemeKeyedCollection baseAddresses)
 102        {
 0103            Uri via = address;
 0104            if (!via.IsAbsoluteUri)
 105            {
 0106                if (!baseAddresses.Contains(scheme))
 107                {
 0108                    return null;
 109                }
 110
 0111                via = GetUri(baseAddresses[scheme], address.OriginalString);
 112            }
 0113            return via;
 114        }
 115
 116        internal static Uri GetUri(Uri baseUri, string path)
 117        {
 0118            if (path.StartsWith("/", StringComparison.Ordinal) || path.StartsWith("\\", StringComparison.Ordinal))
 119            {
 0120                int i = 1;
 0121                for (; i < path.Length; ++i)
 122                {
 0123                    if (path[i] != '/' && path[i] != '\\')
 124                    {
 125                        break;
 126                    }
 127                }
 0128                path = path.Substring(i);
 129            }
 130
 131            // VSWhidbey#541152: new Uri(Uri, string.Empty) is broken
 0132            if (path.Length == 0)
 133            {
 0134                return baseUri;
 135            }
 136
 0137            if (!baseUri.AbsoluteUri.EndsWith("/", StringComparison.Ordinal))
 138            {
 0139                baseUri = new Uri(baseUri.AbsoluteUri + "/");
 140            }
 0141            return new Uri(baseUri, path);
 142        }
 143
 144        internal static ListenUriInfo GetListenUriInfoForEndpoint(ServiceHostBase host, ServiceEndpoint endpoint)
 145        {
 641146            Uri listenUri = EnsureListenUri(host, endpoint);
 641147            return new ListenUriInfo(listenUri, endpoint.ListenUriMode);
 148        }
 149
 150        internal static void InitializeServiceHost(ServiceHostBase serviceHost, IServiceProvider services)
 151        {
 576152            ServiceDescription description = serviceHost.Description;
 576153            if (serviceHost.ImplementedContracts != null && serviceHost.ImplementedContracts.Count > 0)
 154            {
 576155                EnsureThereAreApplicationEndpoints(description);
 156            }
 157
 576158            ValidateDescription(serviceHost);
 159
 576160            var stuffPerListenUriInfo = new Dictionary<ListenUriInfo, StuffPerListenUriInfo>();
 576161            var endpointInfosPerEndpointAddress = new Dictionary<EndpointAddress, Collection<EndpointInfo>>();
 162
 163            // Ensure ListenUri and group endpoints per ListenUri
 2434164            for (int i = 0; i < description.Endpoints.Count; i++)
 165            {
 641166                ServiceEndpoint endpoint = description.Endpoints[i];
 167
 641168                ListenUriInfo listenUriInfo = GetListenUriInfoForEndpoint(serviceHost, endpoint);
 641169                if (!stuffPerListenUriInfo.ContainsKey(listenUriInfo))
 170                {
 640171                    StuffPerListenUriInfo stuff = new StuffPerListenUriInfo();
 640172                    stuff.Parameters.Add(services);
 640173                    stuffPerListenUriInfo.Add(listenUriInfo, stuff);
 174                }
 641175                stuffPerListenUriInfo[listenUriInfo].Endpoints.Add(endpoint);
 176            }
 177
 2432178            foreach (KeyValuePair<ListenUriInfo, StuffPerListenUriInfo> stuff in stuffPerListenUriInfo)
 179            {
 640180                Uri listenUri = stuff.Key.ListenUri;
 640181                BindingParameterCollection parameters = stuff.Value.Parameters;
 640182                Binding binding = stuff.Value.Endpoints[0].Binding;
 640183                EndpointIdentity identity = stuff.Value.Endpoints[0].Address.Identity;
 184                // same EndpointAddressTable instance must be shared between channelDispatcher and parameters
 185                //ThreadSafeMessageFilterTable<EndpointAddress> endpointAddressTable = new ThreadSafeMessageFilterTable<
 186                //parameters.Add(endpointAddressTable);
 187
 188                // add service-level binding parameters
 5414189                foreach (IServiceBehavior behavior in description.Behaviors)
 190                {
 2067191                    behavior.AddBindingParameters(description, serviceHost, stuff.Value.Endpoints, parameters);
 192                }
 2562193                for (int i = 0; i < stuff.Value.Endpoints.Count; i++)
 194                {
 641195                    ServiceEndpoint endpoint = stuff.Value.Endpoints[i];
 641196                    string viaString = listenUri.AbsoluteUri;
 197
 198                    // ensure all endpoints with this ListenUriInfo have same binding
 641199                    if (endpoint.Binding != binding)
 200                    {
 0201                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Forma
 202                    }
 203
 204                    // ensure all endpoints with this ListenUriInfo have same identity
 641205                    if (!Equals(endpoint.Address.Identity, identity))
 206                    {
 0207                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
 0208                                                                                      SR.Format(SR.SFxWhenMultipleEndpoi
 209                    }
 210
 211                    // add binding parameters (endpoint scope and below)
 641212                    AddBindingParametersForSecurityContractInformation(endpoint, parameters);
 641213                    AddBindingParameters(endpoint, parameters);
 214                }
 215
 640216                List<Type> channelTypes = GetSupportedChannelTypes(stuff.Value);
 217
 640218                var bindingQname = new XmlQualifiedName(binding.Name, binding.Namespace);
 640219                var channelDispatcher = new ChannelDispatcher(listenUri, binding, bindingQname.ToString(), binding, chan
 220                //channelDispatcher.SetEndpointAddressTable(endpointAddressTable);
 640221                stuff.Value.ChannelDispatcher = channelDispatcher;
 222
 2562223                for (int i = 0; i < stuff.Value.Endpoints.Count; i++)
 224                {
 641225                    ServiceEndpoint endpoint = stuff.Value.Endpoints[i];
 226
 227                    //EndpointFilterProvider provider = new EndpointFilterProvider();
 641228                    EndpointDispatcher dispatcher = BuildEndpointDispatcher(description, endpoint);
 229
 641230                    if (!endpointInfosPerEndpointAddress.ContainsKey(endpoint.Address))
 231                    {
 640232                        endpointInfosPerEndpointAddress.Add(endpoint.Address, new Collection<EndpointInfo>());
 233                    }
 234
 641235                    endpointInfosPerEndpointAddress[endpoint.Address].Add(new EndpointInfo(endpoint, dispatcher, /*provi
 641236                    channelDispatcher.Endpoints.Add(dispatcher);
 237                } // end foreach "endpoint"
 238
 640239                serviceHost.ChannelDispatchers.Add(channelDispatcher);
 240            } // end foreach "ListenUri/ChannelDispatcher" group
 241
 242            // run service behaviors
 4850243            for (int i = 0; i < description.Behaviors.Count; i++)
 244            {
 1849245                IServiceBehavior serviceBehavior = description.Behaviors[i];
 1849246                serviceBehavior.ApplyDispatchBehavior(description, serviceHost);
 247            }
 248
 2432249            foreach (KeyValuePair<ListenUriInfo, StuffPerListenUriInfo> stuff in stuffPerListenUriInfo)
 250            {
 2562251                for (int i = 0; i < stuff.Value.Endpoints.Count; i++)
 252                {
 641253                    ServiceEndpoint endpoint = stuff.Value.Endpoints[i];
 254                    // rediscover which dispatcher goes with this endpoint
 641255                    Collection<EndpointInfo> infos = endpointInfosPerEndpointAddress[endpoint.Address];
 641256                    EndpointInfo info = null;
 1925257                    foreach (EndpointInfo ei in infos)
 258                    {
 642259                        if (ei.Endpoint == endpoint)
 260                        {
 641261                            info = ei;
 641262                            break;
 263                        }
 264                    }
 641265                    EndpointDispatcher dispatcher = info.EndpointDispatcher;
 266                    // run contract behaviors
 2576267                    for (int k = 0; k < endpoint.Contract.Behaviors.Count; k++)
 268                    {
 647269                        IContractBehavior behavior = endpoint.Contract.Behaviors[k];
 647270                        behavior.ApplyDispatchBehavior(endpoint.Contract, endpoint, dispatcher.DispatchRuntime);
 271                    }
 272                    // run endpoint behaviors
 641273                    ApplyBindingInformationFromEndpointToDispatcher(endpoint, dispatcher);
 2720274                    for (int j = 0; j < endpoint.Behaviors.Count; j++)
 275                    {
 719276                        IEndpointBehavior eb = endpoint.Behaviors[j];
 719277                        eb.ApplyDispatchBehavior(endpoint, dispatcher);
 278                    }
 279                    // run operation behaviors
 641280                    BindOperations(endpoint.Contract, null, dispatcher.DispatchRuntime);
 281                }
 282            }
 283
 576284            EnsureRequiredRuntimeProperties(endpointInfosPerEndpointAddress);
 285
 286            // Warn about obvious demux conflicts
 2432287            foreach (Collection<EndpointInfo> endpointInfos in endpointInfosPerEndpointAddress.Values)
 288            {
 289                // all elements of endpointInfos share the same Address (and thus EndpointListener.AddressFilter)
 640290                if (endpointInfos.Count > 1)
 291                {
 6292                    for (int i = 0; i < endpointInfos.Count; i++)
 293                    {
 6294                        for (int j = i + 1; j < endpointInfos.Count; j++)
 295                        {
 296                            // if not same ListenUri, won't conflict
 297                            // if not same ChannelType, may not conflict (some transports demux based on this)
 298                            // if they share a ChannelDispatcher, this means same ListenUri and same ChannelType
 1299                            if (endpointInfos[i].EndpointDispatcher.ChannelDispatcher ==
 1300                                endpointInfos[j].EndpointDispatcher.ChannelDispatcher)
 301                            {
 1302                                EndpointFilterProvider iProvider = endpointInfos[i].FilterProvider;
 1303                                EndpointFilterProvider jProvider = endpointInfos[j].FilterProvider;
 304                                // if not default EndpointFilterProvider, we won't try to throw, you're on your own
 1305                                if (iProvider != null && jProvider != null
 1306                                    && HaveCommonInitiatingActions(iProvider, jProvider, out string commonAction))
 307                                {
 308                                    // you will definitely get a MultipleFiltersMatchedException at runtime,
 309                                    // so let's go ahead and throw now
 0310                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0311                                        new InvalidOperationException(
 0312                                            SR.Format(SR.SFxDuplicateInitiatingActionAtSameVia, endpointInfos[i].Endpoin
 313                                }
 314                            }
 315                        }
 316                    }
 317                }
 318            }
 576319        }
 320
 321        private static void EnsureRequiredRuntimeProperties(Dictionary<EndpointAddress, Collection<EndpointInfo>> endpoi
 322        {
 2432323            foreach (Collection<EndpointInfo> endpointInfos in endpointInfosPerEndpointAddress.Values)
 324            {
 2562325                for (int i = 0; i < endpointInfos.Count; i++)
 326                {
 641327                    DispatchRuntime dispatch = endpointInfos[i].EndpointDispatcher.DispatchRuntime;
 328
 641329                    if (dispatch.InstanceContextProvider == null)
 330                    {
 0331                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Forma
 332                    }
 333                }
 334            }
 576335        }
 336
 337        private static List<Type> GetSupportedChannelTypes(StuffPerListenUriInfo stuff)
 338        {
 640339            Binding originalBinding = stuff.Endpoints[0].Binding;
 640340            CustomBinding binding = new CustomBinding(originalBinding);
 341
 342            // All types are supported to start
 640343            bool reply = true;
 640344            bool replySession = true;
 640345            bool input = true;
 640346            bool inputSession = true;
 640347            bool duplex = true;
 640348            bool duplexSession = true;
 640349            string sessionContractName = null;
 640350            string datagramContractName = null;
 351            // each endpoint adds constraints
 2562352            for (int i = 0; i < stuff.Endpoints.Count; ++i)
 353            {
 641354                ContractDescription contract = stuff.Endpoints[i].Contract;
 641355                if (contract.SessionMode == SessionMode.Required)
 356                {
 9357                    sessionContractName = contract.Name;
 358                }
 641359                if (contract.SessionMode == SessionMode.NotAllowed)
 360                {
 0361                    datagramContractName = contract.Name;
 362                }
 363
 641364                System.Collections.IList endpointTypes = GetSupportedChannelTypes(contract);
 641365                if (!endpointTypes.Contains(typeof(IReplyChannel)))
 366                {
 11367                    reply = false;
 368                }
 641369                if (!endpointTypes.Contains(typeof(IReplySessionChannel)))
 370                {
 2371                    replySession = false;
 372                }
 641373                if (!endpointTypes.Contains(typeof(IInputChannel)))
 374                {
 589375                    input = false;
 376                }
 641377                if (!endpointTypes.Contains(typeof(IInputSessionChannel)))
 378                {
 589379                    inputSession = false;
 380                }
 641381                if (!endpointTypes.Contains(typeof(IDuplexChannel)))
 382                {
 9383                    duplex = false;
 384                }
 641385                if (!endpointTypes.Contains(typeof(IDuplexSessionChannel)))
 386                {
 0387                    duplexSession = false;
 388                }
 389            }
 390
 640391            if ((sessionContractName != null) && (datagramContractName != null))
 392            {
 0393                string text = SR.Format(SR.SFxCannotRequireBothSessionAndDatagram3, datagramContractName, sessionContrac
 0394                Exception error = new InvalidOperationException(text);
 0395                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
 396            }
 397
 398            // TODO: Restrict list further based on SessionMode constraints
 399
 640400            var supportedChannelTypes = new List<Type>();
 640401            if (input)
 402            {
 52403                supportedChannelTypes.Add(typeof(IInputChannel));
 404            }
 640405            if (inputSession)
 406            {
 52407                supportedChannelTypes.Add(typeof(IInputSessionChannel));
 408            }
 640409            if (reply)
 410            {
 629411                supportedChannelTypes.Add(typeof(IReplyChannel));
 412            }
 640413            if (replySession)
 414            {
 638415                supportedChannelTypes.Add(typeof(IReplySessionChannel));
 416            }
 640417            if (duplex)
 418            {
 631419                supportedChannelTypes.Add(typeof(IDuplexChannel));
 420            }
 640421            if (duplexSession)
 422            {
 640423                supportedChannelTypes.Add(typeof(IDuplexSessionChannel));
 424            }
 425
 640426            return supportedChannelTypes;
 427        }
 428
 429        private static Type[] GetSupportedChannelTypes(ContractDescription contractDescription)
 430        {
 641431            if (contractDescription == null)
 432            {
 0433                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(contractDescr
 434            }
 435
 641436            ChannelRequirements.ComputeContractRequirements(contractDescription, out ChannelRequirements reqs);
 641437            Type[] supportedChannels = ChannelRequirements.ComputeRequiredChannels(ref reqs);
 438            // supportedChannels is client-side, need to make server-side
 6574439            for (int i = 0; i < supportedChannels.Length; i++)
 440            {
 2646441                if (supportedChannels[i] == typeof(IRequestChannel))
 442                {
 630443                    supportedChannels[i] = typeof(IReplyChannel);
 444                }
 2016445                else if (supportedChannels[i] == typeof(IRequestSessionChannel))
 446                {
 639447                    supportedChannels[i] = typeof(IReplySessionChannel);
 448                }
 1377449                else if (supportedChannels[i] == typeof(IOutputChannel))
 450                {
 52451                    supportedChannels[i] = typeof(IInputChannel);
 452                }
 1325453                else if (supportedChannels[i] == typeof(IOutputSessionChannel))
 454                {
 52455                    supportedChannels[i] = typeof(IInputSessionChannel);
 456                }
 1273457                else if (supportedChannels[i] == typeof(IDuplexChannel))
 458                {
 459                    // no-op; duplex is its own dual
 460                }
 641461                else if (supportedChannels[i] == typeof(IDuplexSessionChannel))
 462                {
 463                    // no-op; duplex is its own dual
 464                }
 465                else
 466                {
 0467                    throw Fx.AssertAndThrowFatal("DispatcherBuilder.GetSupportedChannelTypes: Unexpected channel type");
 468                }
 469            }
 470
 641471            return supportedChannels;
 472        }
 473
 474        internal static EndpointDispatcher BuildEndpointDispatcher(ServiceDescription serviceDescription,
 475                                                  ServiceEndpoint endpoint)
 476        {
 641477            if (serviceDescription == null)
 478            {
 0479                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serviceDescription));
 480            }
 481
 641482            ContractDescription contractDescription = endpoint.Contract;
 641483            if (contractDescription == null)
 484            {
 0485                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(endpoint.Contract));
 486            }
 487
 641488            EndpointFilterProvider provider = new EndpointFilterProvider();
 489
 641490            EndpointAddress address = endpoint.Address;
 641491            EndpointDispatcher dispatcher = new EndpointDispatcher(address, contractDescription.Name, contractDescriptio
 492
 641493            DispatchRuntime dispatch = dispatcher.DispatchRuntime;
 641494            if (contractDescription.CallbackContractType != null)
 495            {
 2496                dispatch.CallbackClientRuntime.CallbackClientType = contractDescription.CallbackContractType;
 2497                dispatch.CallbackClientRuntime.ContractClientType = contractDescription.ContractType;
 498            }
 499
 7338500            for (int i = 0; i < contractDescription.Operations.Count; i++)
 501            {
 3028502                OperationDescription operation = contractDescription.Operations[i];
 503
 3028504                if (!operation.IsServerInitiated())
 505                {
 3026506                    BuildDispatchOperation(operation, dispatch, provider, serviceDescription.ServiceProvider);
 507                }
 508                else
 509                {
 2510                    BuildProxyOperation(operation, dispatch.CallbackClientRuntime);
 511                }
 512            }
 513
 514            //dispatcher.SetSupportedChannels(DispatcherBuilder.GetSupportedChannelTypes(contractDescription));
 641515            dispatcher.ContractFilter = provider.CreateFilter(out int filterPriority);
 641516            dispatcher.FilterPriority = filterPriority;
 517
 641518            return dispatcher;
 519        }
 520
 521        private static void BuildProxyOperation(OperationDescription operation, ClientRuntime parent)
 522        {
 523            ClientOperation child;
 2524            if (operation.Messages.Count == 1)
 525            {
 0526                child = new ClientOperation(parent, operation.Name, operation.Messages[0].Action);
 527            }
 528            else
 529            {
 2530                child = new ClientOperation(parent, operation.Name, operation.Messages[0].Action,
 2531                                            operation.Messages[1].Action);
 532            }
 2533            child.TaskMethod = operation.TaskMethod;
 2534            child.TaskTResult = operation.TaskTResult;
 2535            child.SyncMethod = operation.SyncMethod;
 2536            child.BeginMethod = operation.BeginMethod;
 2537            child.EndMethod = operation.EndMethod;
 2538            child.IsOneWay = operation.IsOneWay;
 2539            child.IsTerminating = operation.IsTerminating;
 2540            child.IsInitiating = operation.IsInitiating;
 2541            child.IsSessionOpenNotificationEnabled = operation.IsSessionOpenNotificationEnabled;
 4542            for (int i = 0; i < operation.Faults.Count; i++)
 543            {
 0544                FaultDescription fault = operation.Faults[i];
 0545                child.FaultContractInfos.Add(new FaultContractInfo(fault.Action, fault.DetailType, fault.ElementName, fa
 546            }
 547
 2548            parent.Operations.Add(child);
 2549        }
 550
 551        private static void BuildDispatchOperation(OperationDescription operation, DispatchRuntime parent, EndpointFilte
 552            IServiceProvider services)
 553        {
 3026554            string requestAction = operation.Messages[0].Action;
 555            DispatchOperation child;
 3026556            if (operation.IsOneWay)
 557            {
 324558                child = new DispatchOperation(parent, operation.Name, requestAction);
 559            }
 560            else
 561            {
 2702562                string replyAction = operation.Messages[1].Action;
 2702563                child = new DispatchOperation(parent, operation.Name, requestAction, replyAction);
 564            }
 565
 3026566            child.HasNoDisposableParameters = operation.HasNoDisposableParameters;
 567
 3026568            child.IsTerminating = operation.IsTerminating;
 3026569            child.IsSessionOpenNotificationEnabled = operation.IsSessionOpenNotificationEnabled;
 6376570            for (int i = 0; i < operation.Faults.Count; i++)
 571            {
 162572                FaultDescription fault = operation.Faults[i];
 162573                child.FaultContractInfos.Add(new FaultContractInfo(fault.Action, fault.DetailType, fault.ElementName, fa
 574            }
 575
 3026576            if (provider != null)
 577            {
 3026578                if (operation.IsInitiating)
 579                {
 3018580                    provider.InitiatingActions.Add(requestAction);
 581                }
 582            }
 583
 3026584            if (requestAction != MessageHeaders.WildcardAction)
 585            {
 3016586                parent.Operations.Add(child);
 587            }
 588            else
 589            {
 10590                if (parent.HasMatchAllOperation)
 591                {
 0592                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.SFxMultip
 593                }
 594
 10595                parent.UnhandledDispatchOperation = child;
 596            }
 597
 3026598            var authorizationPolicyProvider = services.GetService<IAuthorizationPolicyProvider>();
 3026599            if (authorizationPolicyProvider != null)
 600            {
 279601                child.AuthorizationPolicy = new Lazy<AuthorizationPolicy>(() =>
 279602                {
 55603                    object serviceInstance = OperationContext.Current.InstanceContext.GetServiceInstance();
 55604                    Type serviceType = serviceInstance.GetType();
 55605                    ReadOnlyCollection<IAuthorizeData> authorizeData = operation.AuthorizeData.ContainsKey(serviceType)
 55606                        ? operation.AuthorizeData[serviceType]
 55607                        : operation.AuthorizeData[serviceType] = BuildAuthorizeData(operation, serviceType);
 279608
 55609                    if (authorizeData.Count > 0)
 279610                    {
 279611                        // TODO: Make this chain call async
 54612                        return AuthorizationPolicy.CombineAsync(authorizationPolicyProvider, authorizeData).GetAwaiter()
 54613                            .GetResult();
 279614                    }
 279615
 1616                    return null;
 279617                });
 618            }
 3026619        }
 620
 621        private static ReadOnlyCollection<IAuthorizeData> BuildAuthorizeData(OperationDescription operation, Type servic
 622        {
 55623            List<IAuthorizeData> authorizeData = new();
 55624            authorizeData.AddRange(serviceType.GetCustomAttributes(false).OfType<IAuthorizeData>());
 625
 55626            Type declaringType = operation.OperationMethod.DeclaringType;
 627
 628            // Check if the declaring type is an interface (split contract and implementation)
 55629            if (declaringType.IsInterface)
 630            {
 53631                InterfaceMapping interfaceMapping = serviceType.GetInterfaceMap(declaringType);
 53632                int index = Array.IndexOf(interfaceMapping.InterfaceMethods, operation.OperationMethod);
 53633                if (index >= 0)
 634                {
 53635                    authorizeData.AddRange(interfaceMapping.TargetMethods[index].GetCustomAttributes(false).OfType<IAuth
 636                }
 637            }
 638            else
 639            {
 640                // The declaring type is the service class itself (contract defined on class)
 641                // Directly get attributes from the operation method
 2642                authorizeData.AddRange(operation.OperationMethod.GetCustomAttributes(false).OfType<IAuthorizeData>());
 643            }
 644
 55645            return authorizeData.AsReadOnly();
 646        }
 647
 648        private static void BindOperations(ContractDescription contract, ClientRuntime proxy, DispatchRuntime dispatch)
 649        {
 641650            if (!(((proxy == null) != (dispatch == null))))
 651            {
 0652                throw Fx.AssertAndThrowFatal("DispatcherBuilder.BindOperations: ((proxy == null) != (dispatch == null))"
 653            }
 654
 641655            MessageDirection local = (proxy == null) ? MessageDirection.Input : MessageDirection.Output;
 656
 7338657            for (int i = 0; i < contract.Operations.Count; i++)
 658            {
 3028659                OperationDescription operation = contract.Operations[i];
 3028660                MessageDescription first = operation.Messages[0];
 661
 3028662                if (first.Direction != local)
 663                {
 2664                    if (proxy == null)
 665                    {
 2666                        proxy = dispatch.CallbackClientRuntime;
 667                    }
 668
 2669                    ClientOperation proxyOperation = proxy.Operations[operation.Name];
 670                    Fx.Assert(proxyOperation != null, "");
 671
 16672                    for (int j = 0; j < operation.Behaviors.Count; j++)
 673                    {
 6674                        IOperationBehavior behavior = operation.Behaviors[j];
 6675                        behavior.ApplyClientBehavior(operation, proxyOperation);
 676                    }
 677                }
 678                else
 679                {
 3026680                    if (dispatch == null)
 681                    {
 0682                        dispatch = proxy.CallbackDispatchRuntime;
 683                    }
 684
 3026685                    DispatchOperation dispatchOperation = null;
 3026686                    if (dispatch.Operations.Contains(operation.Name))
 687                    {
 3016688                        dispatchOperation = dispatch.Operations[operation.Name];
 689                    }
 3026690                    if (dispatchOperation == null && dispatch.UnhandledDispatchOperation != null && dispatch.UnhandledDi
 691                    {
 10692                        dispatchOperation = dispatch.UnhandledDispatchOperation;
 693                    }
 694
 3026695                    if (dispatchOperation != null)
 696                    {
 697                        // Applying authorizations before behaviors so that behaviors can be used validate or customize
 698                        // any claims that have been applied.
 6368699                        for (int k = 0; k < operation.AuthorizeOperation.Count; k++)
 700                        {
 158701                            IAuthorizeOperation authorizeOperation = operation.AuthorizeOperation[k];
 158702                            authorizeOperation.BuildClaim(operation, dispatchOperation);
 703                        }
 704
 24580705                        for (int j = 0; j < operation.Behaviors.Count; j++)
 706                        {
 9264707                            IOperationBehavior behavior = operation.Behaviors[j];
 9264708                            behavior.ApplyDispatchBehavior(operation, dispatchOperation);
 709                        }
 710                    }
 711                }
 712            }
 641713        }
 714
 715        private static bool HaveCommonInitiatingActions(EndpointFilterProvider x, EndpointFilterProvider y, out string c
 716        {
 0717            commonAction = null;
 0718            foreach (string action in x.InitiatingActions)
 719            {
 0720                if (y.InitiatingActions.Contains(action))
 721                {
 0722                    commonAction = action;
 0723                    return true;
 724                }
 725            }
 0726            return false;
 0727        }
 728
 729        internal static List<IServiceDispatcher> BuildDispatcher<TService>(ServiceConfiguration<TService> serviceConfig,
 730        {
 583731            IServiceBuilder serviceBuilder = services.GetRequiredService<IServiceBuilder>();
 583732            Uri[] serverUriAddresses = serviceBuilder.BaseAddresses.ToArray();
 733            ServiceHostObjectModel<TService> serviceHost;
 583734            serviceHost = services.GetRequiredService<ServiceHostObjectModel<TService>>();
 735
 576736            AllServicesConfigurationDelegateHolder allServicesConfigDelegate = services.GetService<AllServicesConfigurat
 576737            ServiceConfigurationDelegateHolder<TService> configDelegate = services.GetService<ServiceConfigurationDelega
 576738            var options = new ServiceOptions<TService>(serviceHost);
 1332739            foreach (var serverUriAddress in serverUriAddresses)
 740            {
 90741                options.BaseAddresses.Add(serverUriAddress);
 742            }
 743
 576744            options.ApplyOptions(configDelegate);
 745
 746            // TODO: Create internal behavior which configures any extensibilities which exist in serviceProvider, eg IM
 2434747            foreach (ServiceEndpointConfiguration endpointConfig in serviceConfig.Endpoints)
 748            {
 641749                if (!serviceHost.ReflectedContracts.Contains(endpointConfig.Contract))
 750                {
 0751                    throw new ArgumentException($"Service type {typeof(TService)} doesn't implement interface {endpointC
 752                }
 753
 641754                ContractDescription contract = serviceHost.ReflectedContracts[endpointConfig.Contract];
 641755                Uri uri = serviceHost.MakeAbsoluteUri(endpointConfig.Address, endpointConfig.Binding);
 641756                var serviceEndpoint = new ServiceEndpoint(
 641757                    contract,
 641758                    endpointConfig.Binding,
 641759                    new EndpointAddress(uri));
 760
 641761                if (endpointConfig.ConfigureEndpoint != null)
 762                {
 37763                    serviceEndpoint.Behaviors.Add(new EndpointConfiguratorEndpointBehavior(endpointConfig.ConfigureEndpo
 764                }
 765
 641766                serviceHost.Description.Endpoints.Add(serviceEndpoint);
 767            }
 768
 576769            configDelegate?.Configure(serviceHost);
 576770            allServicesConfigDelegate?.Configure(serviceHost);
 576771            InitializeServiceHost(serviceHost, services);
 772
 773            // TODO: Add error checking to make sure property chain is correctly populated with objects
 576774            var dispatchers = new List<IServiceDispatcher>(serviceHost.ChannelDispatchers.Count);
 2429775            foreach (ChannelDispatcherBase cdb in serviceHost.ChannelDispatchers)
 776            {
 640777                var cd = cdb as ChannelDispatcher;
 640778                cd.Init();
 637779                System.Threading.Tasks.Task openTask = cd.OpenAsync();
 780                Fx.Assert(openTask.IsCompleted, "ChannelDispatcher should open synchronously");
 637781                openTask.GetAwaiter().GetResult();
 637782                dispatchers.Add(new ServiceDispatcher(cd));
 783            }
 784
 573785            return dispatchers;
 786        }
 787
 788        public static void ApplyBindingInformationFromEndpointToDispatcher(ServiceEndpoint serviceEndpoint, EndpointDisp
 789        {
 641790            endpointDispatcher.ChannelDispatcher.ReceiveSynchronously = false; // No sync code for .Net Core
 641791            endpointDispatcher.ChannelDispatcher.ManualAddressing = IsManualAddressing(serviceEndpoint.Binding);
 641792            endpointDispatcher.ChannelDispatcher.EnableFaults = true;
 641793            endpointDispatcher.ChannelDispatcher.MessageVersion = serviceEndpoint.Binding.MessageVersion;
 641794        }
 795
 796        internal static bool IsManualAddressing(Binding binding)
 797        {
 641798            TransportBindingElement transport = binding.CreateBindingElements().Find<TransportBindingElement>();
 641799            if (transport == null)
 800            {
 0801                string text = SR.Format(SR.SFxBindingMustContainTransport2, binding.Name, binding.Namespace);
 0802                Exception error = new InvalidOperationException(text);
 0803                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
 804            }
 641805            return transport.ManualAddressing;
 806        }
 807
 808        public static void AddBindingParametersForSecurityContractInformation(ServiceEndpoint endpoint, BindingParameter
 809        {
 810            // get Contract info security needs, and put in BindingParameterCollection
 641811            ISecurityCapabilities isc = null;
 641812            BindingElementCollection elements = endpoint.Binding.CreateBindingElements();
 3642813            for (int i = 0; i < elements.Count; ++i)
 814            {
 1214815                if (!(elements[i] is ITransportTokenAssertionProvider))
 816                {
 1159817                    ISecurityCapabilities tmp = elements[i].GetIndividualProperty<ISecurityCapabilities>();
 1159818                    if (tmp != null)
 819                    {
 34820                        isc = tmp;
 34821                        break;
 822                    }
 823                }
 824            }
 641825            if (isc != null)
 826            {
 827                // ensure existence of binding parameter
 34828                ChannelProtectionRequirements requirements = parameters.Find<ChannelProtectionRequirements>();
 34829                if (requirements == null)
 830                {
 34831                    requirements = new ChannelProtectionRequirements();
 34832                    parameters.Add(requirements);
 833                }
 834
 34835                MessageEncodingBindingElement encoding = elements.Find<MessageEncodingBindingElement>();
 836                // use endpoint.Binding.Version
 34837                if (encoding != null && encoding.MessageVersion.Addressing == AddressingVersion.None)
 838                {
 839                    // This binding does not support response actions, so...
 6840                    requirements.Add(ChannelProtectionRequirements.CreateFromContractAndUnionResponseProtectionRequireme
 841                }
 842                else
 843                {
 28844                    requirements.Add(ChannelProtectionRequirements.CreateFromContract(endpoint.Contract, isc));
 845                }
 846            }
 635847        }
 848
 849        #region InnerClasses
 850        private class EndpointInfo
 851        {
 641852            public EndpointInfo(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher, EndpointFilterProvider 
 853            {
 641854                Endpoint = endpoint;
 641855                EndpointDispatcher = endpointDispatcher;
 641856                FilterProvider = provider;
 641857            }
 642858            public ServiceEndpoint Endpoint { get; }
 2859            public EndpointFilterProvider FilterProvider { get; }
 1284860            public EndpointDispatcher EndpointDispatcher { get; }
 861        }
 862
 863        internal class ListenUriInfo
 864        {
 641865            public ListenUriInfo(Uri listenUri, ListenUriMode listenUriMode)
 866            {
 641867                ListenUri = listenUri;
 641868                ListenUriMode = listenUriMode;
 641869            }
 870
 1990871            public Uri ListenUri { get; }
 872
 4873            public ListenUriMode ListenUriMode { get; }
 874
 875            // implement Equals and GetHashCode so that we can use this as a key in a dictionary
 876            public override bool Equals(object obj)
 877            {
 642878                return Equals(obj as ListenUriInfo);
 879            }
 880
 881            public bool Equals(ListenUriInfo other)
 882            {
 642883                if (other == null)
 884                {
 0885                    return false;
 886                }
 887
 642888                if (ReferenceEquals(this, other))
 889                {
 640890                    return true;
 891                }
 892
 2893                return (ListenUriMode == other.ListenUriMode)
 2894                    && EndpointAddress.UriEquals(ListenUri, other.ListenUri, true /* ignoreCase */, true /* includeHost 
 895            }
 896
 897            public override int GetHashCode()
 898            {
 1346899                return EndpointAddress.UriGetHashCode(ListenUri, true /* includeHost */);
 900            }
 901        }
 902
 903        private class StuffPerListenUriInfo
 904        {
 640905            public BindingParameterCollection Parameters = new BindingParameterCollection();
 640906            public Collection<ServiceEndpoint> Endpoints = new Collection<ServiceEndpoint>();
 907            public ChannelDispatcher ChannelDispatcher = null;
 908        }
 909        #endregion // InnerClasses
 910    }
 911}

Methods/Properties

ValidateDescription(CoreWCF.ServiceHostBase)
AddBindingParameters(CoreWCF.Description.ServiceEndpoint,CoreWCF.Channels.BindingParameterCollection)
EnsureThereAreApplicationEndpoints(CoreWCF.Description.ServiceDescription)
EnsureListenUri(CoreWCF.ServiceHostBase,CoreWCF.Description.ServiceEndpoint)
GetVia(System.String,System.Uri,CoreWCF.UriSchemeKeyedCollection)
GetUri(System.Uri,System.String)
GetListenUriInfoForEndpoint(CoreWCF.ServiceHostBase,CoreWCF.Description.ServiceEndpoint)
InitializeServiceHost(CoreWCF.ServiceHostBase,System.IServiceProvider)
EnsureRequiredRuntimeProperties(System.Collections.Generic.Dictionary`2<CoreWCF.EndpointAddress,System.Collections.ObjectModel.Collection`1<CoreWCF.Description.DispatcherBuilder/EndpointInfo>>)
GetSupportedChannelTypes(CoreWCF.Description.DispatcherBuilder/StuffPerListenUriInfo)
GetSupportedChannelTypes(CoreWCF.Description.ContractDescription)
BuildEndpointDispatcher(CoreWCF.Description.ServiceDescription,CoreWCF.Description.ServiceEndpoint)
BuildProxyOperation(CoreWCF.Description.OperationDescription,CoreWCF.Dispatcher.ClientRuntime)
BuildDispatchOperation(CoreWCF.Description.OperationDescription,CoreWCF.Dispatcher.DispatchRuntime,CoreWCF.Dispatcher.EndpointFilterProvider,System.IServiceProvider)
BuildAuthorizeData(CoreWCF.Description.OperationDescription,System.Type)
BindOperations(CoreWCF.Description.ContractDescription,CoreWCF.Dispatcher.ClientRuntime,CoreWCF.Dispatcher.DispatchRuntime)
HaveCommonInitiatingActions(CoreWCF.Dispatcher.EndpointFilterProvider,CoreWCF.Dispatcher.EndpointFilterProvider,System.String&)
BuildDispatcher(CoreWCF.Configuration.ServiceConfiguration`1<TService>,System.IServiceProvider)
ApplyBindingInformationFromEndpointToDispatcher(CoreWCF.Description.ServiceEndpoint,CoreWCF.Dispatcher.EndpointDispatcher)
IsManualAddressing(CoreWCF.Channels.Binding)
AddBindingParametersForSecurityContractInformation(CoreWCF.Description.ServiceEndpoint,CoreWCF.Channels.BindingParameterCollection)
.ctor(CoreWCF.Description.ServiceEndpoint,CoreWCF.Dispatcher.EndpointDispatcher,CoreWCF.Dispatcher.EndpointFilterProvider)
Endpoint()
FilterProvider()
EndpointDispatcher()
.ctor(System.Uri,CoreWCF.Description.ListenUriMode)
ListenUri()
ListenUriMode()
Equals(System.Object)
Equals(CoreWCF.Description.DispatcherBuilder/ListenUriInfo)
GetHashCode()
.ctor()