< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Dispatcher.ImmutableDispatchRuntime
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Dispatcher/ImmutableDispatchRuntime.cs
Line coverage
62%
Covered lines: 282
Uncovered lines: 171
Coverable lines: 453
Total lines: 1133
Line coverage: 62.2%
Branch coverage
60%
Covered branches: 155
Total branches: 256
Branch coverage: 60.5%
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/Dispatcher/ImmutableDispatchRuntime.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.Specialized;
 7using System.Diagnostics;
 8using System.Threading.Tasks;
 9using CoreWCF.Channels;
 10using CoreWCF.Diagnostics;
 11using CoreWCF.Runtime;
 12using CoreWCF.Telemetry;
 13
 14namespace CoreWCF.Dispatcher
 15{
 16    internal class ImmutableDispatchRuntime
 17    {
 18        private readonly AuthenticationBehavior _authenticationBehavior;
 19        private readonly AuthorizationBehavior _authorizationBehavior;
 20        private readonly ConcurrencyBehavior _concurrency;
 21        private readonly IDemuxer _demuxer;
 22        private readonly IInputSessionShutdown[] _inputSessionShutdownHandlers;
 23        private readonly bool _isOnServer;
 24        private readonly IDispatchMessageInspector[] _messageInspectors;
 25        private readonly TerminatingOperationBehavior _terminate;
 26        private readonly ThreadBehavior _thread;
 27        private readonly MessageRpcErrorHandler _processMessageNonCleanupError;
 28        private readonly MessageRpcErrorHandler _processMessageCleanupError;
 29
 30        private Activity? _activity;
 31
 66432        internal ImmutableDispatchRuntime(DispatchRuntime dispatch)
 33        {
 66434            _authenticationBehavior = AuthenticationBehavior.TryCreate(dispatch);
 66435            _authorizationBehavior = AuthorizationBehavior.TryCreate(dispatch);
 66136            _concurrency = new ConcurrencyBehavior(dispatch);
 66137            ErrorBehavior = new ErrorBehavior(dispatch.ChannelDispatcher);
 66138            EnableFaults = dispatch.EnableFaults;
 66139            _inputSessionShutdownHandlers = EmptyArray<IInputSessionShutdown>.ToArray(dispatch.InputSessionShutdownHandl
 66140            InstanceBehavior = new InstanceBehavior(dispatch, this);
 66141            _isOnServer = dispatch.IsOnServer;
 66142            ManualAddressing = dispatch.ManualAddressing;
 66143            _messageInspectors = EmptyArray<IDispatchMessageInspector>.ToArray(dispatch.MessageInspectors);
 66144            SecurityImpersonation = SecurityImpersonationBehavior.CreateIfNecessary(dispatch);
 66145            RequireClaimsPrincipalOnOperationContext = dispatch.RequireClaimsPrincipalOnOperationContext;
 66146            SupportsAuthorizationData = dispatch.SupportsAuthorizationData;
 66147            IsImpersonationEnabledOnSerializingReply = dispatch.ImpersonateOnSerializingReply;
 66148            _terminate = TerminatingOperationBehavior.CreateIfNecessary(dispatch);
 66149            _thread = new ThreadBehavior(dispatch);
 66150            ValidateMustUnderstand = dispatch.ValidateMustUnderstand;
 66151            ParameterInspectorCorrelationOffset = (dispatch.MessageInspectors.Count +
 66152                dispatch.MaxCallContextInitializers);
 66153            CorrelationCount = ParameterInspectorCorrelationOffset + dispatch.MaxParameterInspectors;
 54
 66155            DispatchOperationRuntime unhandled = new DispatchOperationRuntime(dispatch.UnhandledDispatchOperation, this)
 56
 66157            if (dispatch.OperationSelector == null)
 58            {
 62359                ActionDemuxer demuxer = new ActionDemuxer();
 693460                for (int i = 0; i < dispatch.Operations.Count; i++)
 61                {
 284462                    DispatchOperation operation = dispatch.Operations[i];
 284463                    DispatchOperationRuntime operationRuntime = new DispatchOperationRuntime(operation, this);
 284464                    demuxer.Add(operation.Action, operationRuntime);
 65                }
 66
 62367                demuxer.SetUnhandled(unhandled);
 62368                _demuxer = demuxer;
 69            }
 70            else
 71            {
 3872                CustomDemuxer demuxer = new CustomDemuxer(dispatch.OperationSelector);
 41473                for (int i = 0; i < dispatch.Operations.Count; i++)
 74                {
 16975                    DispatchOperation operation = dispatch.Operations[i];
 16976                    DispatchOperationRuntime operationRuntime = new DispatchOperationRuntime(operation, this);
 16977                    demuxer.Add(operation.Name, operationRuntime);
 78                }
 79
 3880                demuxer.SetUnhandled(unhandled);
 3881                _demuxer = demuxer;
 82            }
 83
 66184            _processMessageNonCleanupError = new MessageRpcErrorHandler(ProcessMessageNonCleanupError);
 66185            _processMessageCleanupError = new MessageRpcErrorHandler(ProcessMessageCleanupError);
 66186        }
 87
 88        internal int CallContextCorrelationOffset
 89        {
 2490            get { return _messageInspectors.Length; }
 91        }
 92
 253893        internal int CorrelationCount { get; }
 94
 61895        internal bool EnableFaults { get; }
 96
 812397        internal InstanceBehavior InstanceBehavior { get; }
 98
 61899        internal bool IsImpersonationEnabledOnSerializingReply { get; }
 100
 5033101        internal bool RequireClaimsPrincipalOnOperationContext { get; }
 102
 142103        internal bool SupportsAuthorizationData { get; }
 104
 2184105        internal bool ManualAddressing { get; }
 106
 661107        internal int ParameterInspectorCorrelationOffset { get; }
 108
 109        //        internal IRequestReplyCorrelator RequestReplyCorrelator
 110        //        {
 111        //            get { return this.requestReplyCorrelator; }
 112        //        }
 113
 4984114        internal SecurityImpersonationBehavior SecurityImpersonation { get; }
 115
 2504116        internal bool ValidateMustUnderstand { get; }
 117
 7614118        internal ErrorBehavior ErrorBehavior { get; }
 119
 120        private Task AcquireDynamicInstanceContextAsync(MessageRpc rpc)
 121        {
 2536122            if (rpc.InstanceContext.QuotaThrottle != null)
 123            {
 0124                return AcquireDynamicInstanceContextCoreAsync(rpc);
 125            }
 126            else
 127            {
 2536128                return Task.CompletedTask;
 129            }
 130        }
 131
 132        private Task AcquireDynamicInstanceContextCoreAsync(MessageRpc rpc)
 133        {
 0134            return rpc.InstanceContext.QuotaThrottle.AcquireAsync();
 135        }
 136
 137        internal void AfterReceiveRequest(ref MessageRpc rpc)
 138        {
 2536139            if (_messageInspectors.Length > 0)
 140            {
 3141                AfterReceiveRequestCore(ref rpc);
 142            }
 2536143        }
 144
 145        internal void AfterReceiveRequestCore(ref MessageRpc rpc)
 146        {
 147            try
 148            {
 12149                for (int i = 0; i < _messageInspectors.Length; i++)
 150                {
 3151                    rpc.Correlation[i] = _messageInspectors[i].AfterReceiveRequest(ref rpc.Request, (IClientChannel)rpc.
 152                    //if (TD.MessageInspectorAfterReceiveInvokedIsEnabled())
 153                    //{
 154                    //    TD.MessageInspectorAfterReceiveInvoked(rpc.EventTraceActivity, this.messageInspectors[i].GetTy
 155                    //}
 156                }
 3157            }
 0158            catch (Exception e)
 159            {
 0160                if (Fx.IsFatal(e))
 161                {
 0162                    throw;
 163                }
 0164                if (ErrorBehavior.ShouldRethrowExceptionAsIs(e))
 165                {
 0166                    throw;
 167                }
 0168                throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
 169            }
 3170        }
 171
 172        private void BeforeSendReply(MessageRpc rpc, ref Exception exception, ref bool thereIsAnUnhandledException)
 173        {
 2538174            if (_messageInspectors.Length > 0)
 175            {
 3176                BeforeSendReplyCore(rpc, ref exception, ref thereIsAnUnhandledException);
 177            }
 2538178        }
 179
 180        internal void BeforeSendReplyCore(MessageRpc rpc, ref Exception exception, ref bool thereIsAnUnhandledException)
 181        {
 12182            for (int i = 0; i < _messageInspectors.Length; i++)
 183            {
 184                try
 185                {
 3186                    Message originalReply = rpc.Reply;
 3187                    Message reply = originalReply;
 188
 3189                    _messageInspectors[i].BeforeSendReply(ref reply, rpc.Correlation[i]);
 190                    //if (TD.MessageInspectorBeforeSendInvokedIsEnabled())
 191                    //{
 192                    //    TD.MessageInspectorBeforeSendInvoked(rpc.EventTraceActivity, this.messageInspectors[i].GetType
 193                    //}
 194
 3195                    if ((reply == null) && (originalReply != null))
 196                    {
 0197                        string message = SR.Format(SR.SFxNullReplyFromExtension2, _messageInspectors[i].GetType().ToStri
 0198                        ErrorBehavior.ThrowAndCatch(new InvalidOperationException(message));
 199                    }
 3200                    rpc.Reply = reply;
 3201                }
 0202                catch (Exception e)
 203                {
 0204                    if (Fx.IsFatal(e))
 205                    {
 0206                        throw;
 207                    }
 0208                    if (!ErrorBehavior.ShouldRethrowExceptionAsIs(e))
 209                    {
 0210                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
 211                    }
 212
 0213                    if (exception == null)
 214                    {
 0215                        exception = e;
 216                    }
 0217                    thereIsAnUnhandledException = (!ErrorBehavior.HandleError(e)) || thereIsAnUnhandledException;
 0218                }
 219            }
 3220        }
 221
 222        private async Task<MessageRpc> ReplyAsync(MessageRpc rpc)
 223        {
 728224            rpc.RequestContextThrewOnReply = true;
 728225            rpc.SuccessfullySendReply = false;
 226
 227            try
 228            {
 728229                await rpc.RequestContext.ReplyAsync(rpc.Reply, rpc.ReplyTimeoutHelper.GetCancellationToken());
 728230                rpc.RequestContextThrewOnReply = false;
 728231                rpc.SuccessfullySendReply = true;
 232
 233                //if (TD.DispatchMessageStopIsEnabled())
 234                //{
 235                //    TD.DispatchMessageStop(rpc.EventTraceActivity);
 236                //}
 728237            }
 0238            catch (CommunicationException e)
 239            {
 0240                ErrorBehavior.HandleError(e);
 0241            }
 0242            catch (TimeoutException e)
 243            {
 0244                ErrorBehavior.HandleError(e);
 0245            }
 0246            catch (Exception e)
 247            {
 0248                if (Fx.IsFatal(e))
 249                {
 0250                    throw;
 251                }
 252
 253                //if (DiagnosticUtility.ShouldTraceError)
 254                //{
 255                //    TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.ServiceOperationExceptionOnReply,
 256                //        SR.Format(SR.TraceCodeServiceOperationExceptionOnReply),
 257                //        this, e);
 258                //}
 259
 0260                if (!ErrorBehavior.HandleError(e))
 261                {
 0262                    rpc.RequestContextThrewOnReply = true;
 0263                    rpc.CanSendReply = false;
 264                }
 0265            }
 266
 728267            return rpc;
 728268        }
 269
 270        internal Task<MessageRpc> DispatchAsync(MessageRpc rpc, bool isOperationContextSet)
 271        {
 2538272            rpc.ErrorProcessor = ProcessError;
 2538273            rpc.AsyncProcessor = ProcessMessageAsync;
 2538274            Task<MessageRpc> task = rpc.ProcessAsync(isOperationContextSet);
 2538275            rpc._processCallReturned = true;
 2538276            return task;
 277        }
 278
 279        internal void InputSessionDoneReceiving(ServiceChannel channel)
 280        {
 78281            if (_inputSessionShutdownHandlers.Length > 0)
 282            {
 0283                InputSessionDoneReceivingCore(channel);
 284            }
 78285        }
 286
 287        private void InputSessionDoneReceivingCore(ServiceChannel channel)
 288        {
 0289            if (channel.Proxy is IDuplexContextChannel proxy)
 290            {
 0291                IInputSessionShutdown[] handlers = _inputSessionShutdownHandlers;
 292                try
 293                {
 0294                    for (int i = 0; i < handlers.Length; i++)
 295                    {
 0296                        handlers[i].DoneReceiving(proxy);
 297                    }
 0298                }
 0299                catch (Exception e)
 300                {
 0301                    if (Fx.IsFatal(e))
 302                    {
 0303                        throw;
 304                    }
 0305                    if (!ErrorBehavior.HandleError(e))
 306                    {
 0307                        proxy.Abort();
 308                    }
 0309                }
 310            }
 0311        }
 312
 313        internal bool IsConcurrent(MessageRpc rpc)
 314        {
 0315            return _concurrency.IsConcurrent(rpc);
 316        }
 317
 318        internal void InputSessionFaulted(ServiceChannel channel)
 319        {
 0320            if (_inputSessionShutdownHandlers.Length > 0)
 321            {
 0322                InputSessionFaultedCore(channel);
 323            }
 0324        }
 325
 326        private void InputSessionFaultedCore(ServiceChannel channel)
 327        {
 0328            if (channel.Proxy is IDuplexContextChannel proxy)
 329            {
 0330                IInputSessionShutdown[] handlers = _inputSessionShutdownHandlers;
 331                try
 332                {
 0333                    for (int i = 0; i < handlers.Length; i++)
 334                    {
 0335                        handlers[i].ChannelFaulted(proxy);
 336                    }
 0337                }
 0338                catch (Exception e)
 339                {
 0340                    if (Fx.IsFatal(e))
 341                    {
 0342                        throw;
 343                    }
 0344                    if (!ErrorBehavior.HandleError(e))
 345                    {
 0346                        proxy.Abort();
 347                    }
 0348                }
 349            }
 0350        }
 351
 352        private void AddMessageProperties(Message message, OperationContext context, ServiceChannel replyChannel)
 353        {
 728354            if (context.InternalServiceChannel == replyChannel)
 355            {
 728356                if (context.HasOutgoingMessageHeaders)
 357                {
 0358                    message.Headers.CopyHeadersFrom(context.OutgoingMessageHeaders);
 359                }
 360
 728361                if (context.HasOutgoingMessageProperties)
 362                {
 35363                    message.Properties.MergeProperties(context.OutgoingMessageProperties);
 364                }
 365            }
 728366        }
 367
 368        private async ValueTask PrepareReplyAsync(MessageRpc rpc)
 369        {
 2538370            RequestContext context = rpc.OperationContext.RequestContext;
 2538371            Exception exception = null;
 2538372            bool thereIsAnUnhandledException = false;
 373
 2538374            if (!rpc.Operation.IsOneWay)
 375            {
 376                //if (DiagnosticUtility.ShouldTraceWarning)
 377                //{
 378                //    // If a service both returns null and sets RequestContext null, that
 379                //    // means they handled it (either by calling Close or Reply manually).
 380                //    // These traces catch accidents, where you accidentally return null,
 381                //    // or you accidentally close the context so we can't return your message.
 382                //    if ((rpc.Reply == null) && (context != null))
 383                //    {
 384                //        TraceUtility.TraceEvent(System.Diagnostics.TraceEventType.Warning,
 385                //            TraceCode.ServiceOperationMissingReply,
 386                //            SR.Format(SR.TraceCodeServiceOperationMissingReply, rpc.Operation.Name ?? String.Empty),
 387                //            null, null);
 388                //    }
 389                //    else if ((context == null) && (rpc.Reply != null))
 390                //    {
 391                //        TraceUtility.TraceEvent(System.Diagnostics.TraceEventType.Warning,
 392                //            TraceCode.ServiceOperationMissingReplyContext,
 393                //            SR.Format(SR.TraceCodeServiceOperationMissingReplyContext, rpc.Operation.Name ?? String.Em
 394                //            null, null);
 395                //    }
 396                //}
 397
 728398                if ((context != null) && (rpc.Reply != null))
 399                {
 400                    try
 401                    {
 728402                        rpc.CanSendReply = PrepareAndAddressReply(ref rpc);
 728403                    }
 0404                    catch (Exception e)
 405                    {
 0406                        if (Fx.IsFatal(e))
 407                        {
 0408                            throw;
 409                        }
 0410                        thereIsAnUnhandledException = (!ErrorBehavior.HandleError(e)) || thereIsAnUnhandledException;
 0411                        exception = e;
 0412                    }
 413                }
 414            }
 415
 2538416            if (_activity != null)
 417            {
 2418                var reply = rpc.Reply;
 2419                if (_activity.IsAllDataRequested && reply != null)
 420                {
 2421                    if (reply.IsFault)
 422                    {
 1423                        _activity.SetStatus(ActivityStatusCode.Error);
 424                    }
 425
 2426                    _activity.SetTag(WcfInstrumentationConstants.SoapReplyActionTag, reply.Headers.Action);
 427                }
 428
 2429                _activity.Stop();
 430            }
 431
 2538432            BeforeSendReply(rpc, ref exception, ref thereIsAnUnhandledException);
 433
 2538434            if (rpc.Operation.IsOneWay)
 435            {
 1810436                rpc.CanSendReply = false;
 437            }
 438
 2538439            if (!rpc.Operation.IsOneWay && (context != null) && (rpc.Reply != null))
 440            {
 728441                if (exception != null)
 442                {
 443                    // We don't call ProvideFault again, since we have already passed the
 444                    // point where SFx addresses the reply, and it is reasonable for
 445                    // ProvideFault to expect that SFx will address the reply.  Instead
 446                    // we always just do 'internal server error' processing.
 0447                    rpc.Error = exception;
 0448                    ErrorBehavior.ProvideOnlyFaultOfLastResort(ref rpc);
 449
 450                    try
 451                    {
 0452                        rpc.CanSendReply = PrepareAndAddressReply(ref rpc);
 0453                    }
 0454                    catch (Exception e)
 455                    {
 0456                        if (Fx.IsFatal(e))
 457                        {
 0458                            throw;
 459                        }
 0460                        ErrorBehavior.HandleError(e);
 0461                    }
 462                }
 463            }
 1810464            else if ((exception != null) && thereIsAnUnhandledException)
 465            {
 0466                await rpc.AbortAsync();
 467            }
 2538468        }
 469
 470        private bool PrepareAndAddressReply(ref MessageRpc rpc)
 471        {
 728472            bool canSendReply = true;
 473
 728474            if (!ManualAddressing)
 475            {
 683476                if (!ReferenceEquals(rpc.RequestID, null))
 477                {
 294478                    RequestReplyCorrelator.PrepareReply(rpc.Reply, rpc.RequestID);
 479                }
 480
 683481                if (!rpc.Channel.HasSession)
 482                {
 580483                    canSendReply = RequestReplyCorrelator.AddressReply(rpc.Reply, rpc.ReplyToInfo);
 484                }
 485            }
 486
 728487            AddMessageProperties(rpc.Reply, rpc.OperationContext, rpc.Channel);
 488            //if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled && rpc.EventTraceActivity != null)
 489            //{
 490            //    rpc.Reply.Properties[EventTraceActivity.Name] = rpc.EventTraceActivity;
 491            //}
 492
 728493            return canSendReply;
 494        }
 495
 496        internal DispatchOperationRuntime GetOperation(ref Message message)
 497        {
 2539498            return _demuxer.GetOperation(ref message);
 499        }
 500
 501        private void ReceiveContextRPCFacet_CreatIfRequired_Shim(MessageRpc rpc)
 502        {
 2538503            rpc.ReceiveContext = ReceiveContext.TryGet(rpc.Request, out ReceiveContext receiveContext)
 2538504                ? receiveContext
 2538505                : null;
 2538506        }
 507
 508        internal async Task<MessageRpc> ProcessMessageAsync(MessageRpc rpc)
 509        {
 2538510            ReceiveContextRPCFacet_CreatIfRequired_Shim(rpc);
 511
 2538512            if (rpc.Operation.IsOneWay)
 513            {
 1810514                await rpc.RequestContext.ReplyAsync(null);
 1810515                rpc.OperationContext.RequestContext = null;
 516            }
 517            else
 518            {
 728519                if (!rpc.Channel.IsReplyChannel &&
 728520                    ((object)rpc.RequestID == null) &&
 728521                    (rpc.Operation.Action != MessageHeaders.WildcardAction))
 522                {
 0523                    CommunicationException error = new CommunicationException(SR.SFxOneWayMessageToTwoWayMethod0);
 0524                    throw TraceUtility.ThrowHelperError(error, rpc.Request);
 525                }
 526
 728527                if (!ManualAddressing)
 528                {
 683529                    EndpointAddress replyTo = rpc.ReplyToInfo.ReplyTo;
 683530                    if (replyTo != null && replyTo.IsNone && rpc.Channel.IsReplyChannel)
 531                    {
 0532                        CommunicationException error = new CommunicationException(SR.SFxRequestReplyNone);
 0533                        throw TraceUtility.ThrowHelperError(error, rpc.Request);
 534                    }
 535
 683536                    if (_isOnServer)
 537                    {
 683538                        EndpointAddress remoteAddress = rpc.Channel.RemoteAddress;
 683539                        if ((remoteAddress != null) && !remoteAddress.IsAnonymous)
 540                        {
 0541                            MessageHeaders headers = rpc.Request.Headers;
 0542                            Uri remoteUri = remoteAddress.Uri;
 543
 0544                            if ((replyTo != null) && !replyTo.IsAnonymous && (remoteUri != replyTo.Uri))
 545                            {
 0546                                string text = SR.Format(SR.SFxRequestHasInvalidReplyToOnServer, replyTo.Uri, remoteUri);
 0547                                Exception error = new InvalidOperationException(text);
 0548                                throw TraceUtility.ThrowHelperError(error, rpc.Request);
 549                            }
 550
 0551                            EndpointAddress faultTo = headers.FaultTo;
 0552                            if ((faultTo != null) && !faultTo.IsAnonymous && (remoteUri != faultTo.Uri))
 553                            {
 0554                                string text = SR.Format(SR.SFxRequestHasInvalidFaultToOnServer, faultTo.Uri, remoteUri);
 0555                                Exception error = new InvalidOperationException(text);
 0556                                throw TraceUtility.ThrowHelperError(error, rpc.Request);
 557                            }
 558
 0559                            if (rpc.RequestVersion.Addressing == AddressingVersion.WSAddressingAugust2004)
 560                            {
 0561                                EndpointAddress from = headers.From;
 0562                                if ((from != null) && !from.IsAnonymous && (remoteUri != from.Uri))
 563                                {
 0564                                    string text = SR.Format(SR.SFxRequestHasInvalidFromOnServer, from.Uri, remoteUri);
 0565                                    Exception error = new InvalidOperationException(text);
 0566                                    throw TraceUtility.ThrowHelperError(error, rpc.Request);
 567                                }
 568                            }
 569                        }
 570                    }
 571                }
 572            }
 573
 2538574            if (_concurrency.IsConcurrent(rpc))
 575            {
 2480576                rpc.Channel.IncrementActivity();
 2480577                rpc.SuccessfullyIncrementedActivity = true;
 578            }
 579
 2538580            if (_authenticationBehavior != null)
 581            {
 0582                rpc = await _authenticationBehavior.AuthenticateAsync(rpc);
 583            }
 584
 2538585            if (_authorizationBehavior != null && !SupportsAuthorizationData)
 586            {
 17587                rpc = await _authorizationBehavior.AuthorizeAsync(rpc);
 588            }
 589
 2536590            await InstanceBehavior.EnsureInstanceContextAsync(rpc);
 2536591            TransferChannelFromPendingList(rpc);
 2536592            await AcquireDynamicInstanceContextAsync(rpc);
 593
 2536594            _activity = CreateActivity(ref rpc.Request, (IClientChannel)rpc.Channel.Proxy, rpc.InstanceContext);
 595
 2536596            AfterReceiveRequest(ref rpc);
 597
 2536598            await _concurrency.LockInstanceAsync(rpc);
 2536599            rpc.SuccessfullyLockedInstance = true;
 600
 601            try
 602            {
 603                // TaskHelpers has an extension method which enables awaitting a sync context to run continuation on it.
 2536604                await _thread.GetSyncContext(rpc);
 2536605            }
 0606            catch (Exception e)
 607            {
 0608                if (Fx.IsFatal(e))
 609                {
 0610                    throw;
 611                }
 612
 0613                throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(e.Message, e);
 614            }
 615
 616            // This needs to happen after LockInstance--LockInstance guarantees
 617            // in-order delivery, so we can't receive the next message until we
 618            // have acquired the lock.
 619            //
 620            // This also needs to happen after BindThread based on the assumption
 621            // that running on UI thread should guarantee in-order delivery if
 622            // the SynchronizationContext is single threaded.
 2536623            if (_concurrency.IsConcurrent(rpc))
 624            {
 2478625                rpc.EnsureReceive();
 2478626                if (!rpc._processCallReturned)
 627                {
 628                    // To allow transport receive loop to get next request, the call to dispatch the current message nee
 629                    // If all previous await's have completed synchronously, execution needs to be forced to continue on
 630                    // This code causes this method to continue on another thread and any calling receive pump (such as 
 631                    // use this thread to request the next message. It might be better to switch that so this thread con
 632                    // thread and the caller has to run on a new thread.
 2404633                    await Task.Yield();
 634                }
 635            }
 636
 2536637            InstanceBehavior.EnsureServiceInstance(rpc);
 638
 2535639            if (RequireClaimsPrincipalOnOperationContext)
 640            {
 55641                rpc.Operation.SetClaimsPrincipalToOperationContext(rpc);
 642            }
 643
 2535644            if (_authorizationBehavior != null && SupportsAuthorizationData)
 645            {
 55646                rpc = await _authorizationBehavior.AuthorizePolicyAsync(rpc);
 647            }
 648
 649            try
 650            {
 2505651                SetActivityIdOnThread(rpc);
 2505652                rpc = await rpc.Operation.InvokeAsync(rpc);
 2375653            }
 130654            catch
 655            {
 656                // This catch clause forces ClearCallContext to run prior to stackwalks exiting this frame.
 130657                throw;
 658            }
 659
 660            try
 661            {
 662                // Switch back to thread pool if we're using a non-default Sync Context. This only switches threads if n
 2375663                await TaskHelpers.EnsureDefaultTaskScheduler();
 2375664            }
 0665            catch (Exception e)
 666            {
 0667                if (Fx.IsFatal(e))
 668                {
 0669                    throw;
 670                }
 671
 0672                throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(e.Message, e);
 673            }
 674
 2375675            await ProcessError(rpc);
 676
 2375677            if (!_concurrency.IsConcurrent(rpc))
 678            {
 58679                rpc.EnsureReceive();
 680            }
 681
 2375682            return rpc;
 2375683        }
 684
 685        private Activity CreateActivity(ref Message request, IClientChannel channel, InstanceContext instanceContext)
 686        {
 2536687            var activity = WcfInstrumentationActivitySource.ActivitySource.StartActivity(
 2536688                WcfInstrumentationActivitySource.IncomingRequestActivityName,
 2536689                ActivityKind.Server);
 690
 2536691            if (activity != null)
 692            {
 693                string action;
 2694                if (!string.IsNullOrEmpty(request.Headers.Action))
 695                {
 2696                    action = request.Headers.Action;
 2697                    activity.DisplayName = action;
 698                }
 699                else
 700                {
 0701                    action = string.Empty;
 702                }
 703
 2704                if (activity.IsAllDataRequested)
 705                {
 2706                    activity.SetTag(WcfInstrumentationConstants.RpcSystemTag,
 2707                        WcfInstrumentationConstants.WcfSystemValue);
 708
 2709                    var actionMetadata = GetActionMetadata(request, action);
 710
 2711                    activity.SetTag(WcfInstrumentationConstants.RpcServiceTag, actionMetadata.ContractName);
 2712                    activity.SetTag(WcfInstrumentationConstants.RpcMethodTag, actionMetadata.OperationName);
 2713                    activity.SetTag(WcfInstrumentationConstants.SoapMessageVersionTag, request.Version.ToString());
 714
 2715                    var localAddressUri = channel.LocalAddress?.Uri;
 2716                    if (localAddressUri != null)
 717                    {
 2718                        activity.SetTag(WcfInstrumentationConstants.NetHostNameTag, localAddressUri.Host);
 2719                        activity.SetTag(WcfInstrumentationConstants.NetHostPortTag, localAddressUri.Port);
 2720                        activity.SetTag(WcfInstrumentationConstants.WcfChannelSchemeTag, localAddressUri.Scheme);
 2721                        activity.SetTag(WcfInstrumentationConstants.WcfChannelPathTag, localAddressUri.LocalPath);
 722                    }
 723                }
 724            }
 725
 2536726            return activity;
 727        }
 728
 729        private async Task ProcessError(MessageRpc rpc)
 730        {
 731            try
 732            {
 2538733                ErrorBehavior.ProvideMessageFault(rpc);
 2538734            }
 0735            catch (Exception e)
 736            {
 0737                if (Fx.IsFatal(e))
 738                {
 0739                    throw;
 740                }
 741
 0742                ErrorBehavior.HandleError(e);
 0743            }
 744
 2538745            await PrepareReplyAsync(rpc);
 746
 2538747            if (rpc.CanSendReply)
 748            {
 728749                rpc.ReplyTimeoutHelper = new TimeoutHelper(rpc.Channel.OperationTimeout);
 750                //if (rpc.Reply != null)
 751                //{
 752                //    TraceUtility.MessageFlowAtMessageSent(rpc.Reply, rpc.EventTraceActivity);
 753                //}
 754
 728755                await ReplyAsync(rpc);
 756            }
 757
 2538758            await ProcessMessageCleanupAsync(rpc);
 2538759        }
 760
 761        private static ActionMetadata GetActionMetadata(Message request, string action)
 762        {
 2763            ActionMetadata? actionMetadata = null;
 2764            if (request.Properties.TryGetValue(TelemetryContextMessageProperty.Name, out var telemetryContextProperty))
 765            {
 0766                var actionMappings = (telemetryContextProperty as TelemetryContextMessageProperty)?.ActionMappings;
 0767                if (actionMappings != null && actionMappings.TryGetValue(action, out var metadata))
 768                {
 0769                    actionMetadata = metadata;
 770                }
 771            }
 772
 2773            return actionMetadata ?? new ActionMetadata(
 2774                contractName: null,
 2775                operationName: action);
 776        }
 777
 778        // Logic for knowing when to close stuff:
 779        //
 780        // ASSUMPTIONS:
 781        //   Closing a stream over a message also closes the message.
 782        //   Closing a message over a stream does not close the stream.
 783        //     (OperationStreamProvider.ReleaseStream is no-op)
 784        //
 785        // This is a table of what should be disposed in what cases.
 786        // The rows represent the type of parameter to the method and
 787        // whether we are disposing parameters or not.  The columns
 788        // are for the inputs vs. the outputs.  The cells contain the
 789        // values that need to be Disposed.  M^P means that exactly
 790        // one of the message and parameter needs to be disposed,
 791        // since they refer to the same object.
 792        //
 793        //                               Request           Reply
 794        //               Message   |     M or P      |     M or P
 795        //     Dispose   Stream    |     P           |     M and P
 796        //               Params    |     M and P     |     M and P
 797        //                         |                 |
 798        //               Message   |     none        |     none
 799        //   NoDispose   Stream    |     none        |     M
 800        //               Params    |     M           |     M
 801        //
 802        // By choosing to dispose the parameter in both of the "M or P"
 803        // cases, the logic needed to generate this table is:
 804        //
 805        // CloseRequestMessage = IsParams
 806        // CloseRequestParams  = rpc.Operation.DisposeParameters
 807        // CloseReplyMessage   = rpc.Operation.SerializeReply
 808        // CloseReplyParams    = rpc.Operation.DisposeParameters
 809        //
 810        // IsParams can be calculated based on whether the request
 811        // message was consumed after deserializing but before calling
 812        // the user.  This is stored as rpc.DidDeserializeRequestBody.
 813        //
 814        private async Task ProcessMessageCleanupAsync(MessageRpc rpc)
 815        {
 816            Fx.Assert(
 817                !ReferenceEquals(rpc.ErrorProcessor, _processMessageCleanupError),
 818                "ProcessMessageCleanup run twice on the same MessageRpc!");
 2538819            rpc.ErrorProcessor = _processMessageCleanupError;
 820
 2538821            bool replyWasSent = false;
 822
 2538823            if (rpc.CanSendReply)
 824            {
 728825                replyWasSent = rpc.SuccessfullySendReply;
 826            }
 827
 828            try
 829            {
 830                try
 831                {
 2538832                    if (rpc.DidDeserializeRequestBody)
 833                    {
 2425834                        rpc.Request.Close();
 835                    }
 2538836                }
 0837                catch (Exception e)
 838                {
 0839                    if (Fx.IsFatal(e))
 840                    {
 0841                        throw;
 842                    }
 0843                    ErrorBehavior.HandleError(e);
 0844                }
 845
 2538846                rpc.DisposeParameters(false); //Dispose all input/output/return parameters
 847
 2538848                if (rpc.FaultInfo.IsConsideredUnhandled)
 849                {
 58850                    if (!replyWasSent)
 851                    {
 53852                        await rpc.AbortRequestContextAsync();
 53853                        rpc.AbortChannel();
 854                    }
 855                    else
 856                    {
 5857                        await rpc.CloseRequestContextAsync();
 5858                        await rpc.CloseChannelAsync();
 859                    }
 58860                    rpc.AbortInstanceContext();
 861                }
 862                else
 863                {
 2480864                    if (rpc.RequestContextThrewOnReply)
 865                    {
 0866                        await rpc.AbortRequestContextAsync();
 867                    }
 868                    else
 869                    {
 2480870                        await rpc.CloseRequestContextAsync();
 871                    }
 872                }
 873
 2538874                if ((rpc.Reply != null) && (rpc.Reply != rpc.ReturnParameter))
 875                {
 876                    try
 877                    {
 761878                        rpc.Reply.Close();
 761879                    }
 0880                    catch (Exception e)
 881                    {
 0882                        if (Fx.IsFatal(e))
 883                        {
 0884                            throw;
 885                        }
 0886                        ErrorBehavior.HandleError(e);
 0887                    }
 888                }
 889
 2538890                if ((rpc.FaultInfo.Fault != null) && (rpc.FaultInfo.Fault.State != MessageState.Closed))
 891                {
 892                    // maybe ProvideFault gave a Message, but then BeforeSendReply replaced it
 893                    // in that case, we need to close the one from ProvideFault
 894                    try
 895                    {
 0896                        rpc.FaultInfo.Fault.Close();
 0897                    }
 0898                    catch (Exception e)
 899                    {
 0900                        if (Fx.IsFatal(e))
 901                        {
 0902                            throw;
 903                        }
 0904                        ErrorBehavior.HandleError(e);
 0905                    }
 906                }
 907
 908                try
 909                {
 2538910                    rpc.OperationContext.FireOperationCompleted();
 2538911                }
 912
 0913                catch (Exception e)
 914                {
 0915                    if (Fx.IsFatal(e))
 916                    {
 0917                        throw;
 918                    }
 0919                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
 920                }
 921
 2538922                InstanceBehavior.AfterReply(ref rpc, ErrorBehavior);
 923
 2538924                if (rpc.SuccessfullyLockedInstance)
 925                {
 926                    try
 927                    {
 2536928                        _concurrency.UnlockInstance(ref rpc);
 2536929                    }
 0930                    catch (Exception e)
 931                    {
 0932                        if (Fx.IsFatal(e))
 933                        {
 0934                            throw;
 935                        }
 936
 937                        Fx.Assert("Exceptions should be caught by callee");
 0938                        rpc.InstanceContext.FaultInternal();
 0939                        ErrorBehavior.HandleError(e);
 0940                    }
 941                }
 942
 2538943                if (_terminate != null)
 944                {
 945                    try
 946                    {
 11947                        _terminate.AfterReply(ref rpc);
 11948                    }
 0949                    catch (Exception e)
 950                    {
 0951                        if (Fx.IsFatal(e))
 952                        {
 0953                            throw;
 954                        }
 0955                        ErrorBehavior.HandleError(e);
 0956                    }
 957                }
 958
 2538959                if (rpc.SuccessfullyIncrementedActivity)
 960                {
 961                    try
 962                    {
 2480963                        await rpc.Channel.DecrementActivityAsync();
 2480964                    }
 0965                    catch (Exception e)
 966                    {
 0967                        if (Fx.IsFatal(e))
 968                        {
 0969                            throw;
 970                        }
 0971                        ErrorBehavior.HandleError(e);
 0972                    }
 973                }
 2538974            }
 975            finally
 976            {
 977                // TODO: Add the code for the other half of InstanceContextServiceThrottle being acquired
 2538978                if (rpc.MessageRpcOwnsInstanceContextThrottle && rpc.ChannelHandler.InstanceContextServiceThrottle != nu
 979                {
 0980                    rpc.ChannelHandler.InstanceContextServiceThrottle.DeactivateInstanceContext();
 981                }
 982
 983                //if (rpc.Activity != null && DiagnosticUtility.ShouldUseActivity)
 984                //{
 985                //    rpc.Activity.Stop();
 986                //}
 987            }
 988
 2538989            ErrorBehavior.HandleError(rpc);
 2538990        }
 991
 992        private async Task ProcessMessageNonCleanupError(MessageRpc rpc)
 993        {
 994            try
 995            {
 0996                ErrorBehavior.ProvideMessageFault(rpc);
 0997            }
 0998            catch (Exception e)
 999            {
 01000                if (Fx.IsFatal(e))
 1001                {
 01002                    throw;
 1003                }
 1004
 01005                ErrorBehavior.HandleError(e);
 01006            }
 1007
 01008            await PrepareReplyAsync(rpc);
 01009        }
 1010
 1011        private Task ProcessMessageCleanupError(MessageRpc rpc)
 1012        {
 01013            ErrorBehavior.HandleError(rpc);
 01014            return Task.CompletedTask;
 1015        }
 1016
 1017        private void SetActivityIdOnThread(MessageRpc rpc)
 1018        {
 1019            //if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled && rpc.EventTraceActivity != null)
 1020            //{
 1021            //    // Propogate the ActivityId to the service operation
 1022            //    EventTraceActivityHelper.SetOnThread(rpc.EventTraceActivity);
 1023            //}
 25051024        }
 1025
 1026        private void TransferChannelFromPendingList(MessageRpc rpc)
 1027        {
 25361028            if (rpc.Channel.IsPending)
 1029            {
 5131030                rpc.Channel.IsPending = false;
 1031
 5131032                ChannelDispatcher channelDispatcher = rpc.Channel.ChannelDispatcher;
 5131033                IInstanceContextProvider provider = InstanceBehavior.InstanceContextProvider;
 1034
 5131035                if (!InstanceContextProviderBase.IsProviderSessionful(provider) &&
 5131036                    !InstanceContextProviderBase.IsProviderSingleton(provider))
 1037                {
 131038                    IChannel proxy = rpc.Channel.Proxy as IChannel;
 131039                    if (!rpc.InstanceContext.IncomingChannels.Contains(proxy))
 1040                    {
 131041                        channelDispatcher.Channels.Add(proxy);
 1042                    }
 1043                }
 1044
 1045                // TODO: Do we need to keep track of pending channels with the new hosting model?
 1046                //channelDispatcher.PendingChannels.Remove(rpc.Channel.Binder.Channel);
 1047            }
 25361048        }
 1049
 1050        private interface IDemuxer
 1051        {
 1052            DispatchOperationRuntime GetOperation(ref Message request);
 1053        }
 1054
 1055        private class ActionDemuxer : IDemuxer
 1056        {
 1057            private readonly HybridDictionary _map;
 1058            private DispatchOperationRuntime _unhandled;
 1059
 6231060            internal ActionDemuxer()
 1061            {
 6231062                _map = new HybridDictionary();
 6231063            }
 1064
 1065            internal void Add(string action, DispatchOperationRuntime operation)
 1066            {
 28441067                if (_map.Contains(action))
 1068                {
 01069                    DispatchOperationRuntime existingOperation = (DispatchOperationRuntime)_map[action];
 01070                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR
 1071                }
 28441072                _map.Add(action, operation);
 28441073            }
 1074
 1075            internal void SetUnhandled(DispatchOperationRuntime operation)
 1076            {
 6231077                _unhandled = operation;
 6231078            }
 1079
 1080            public DispatchOperationRuntime GetOperation(ref Message request)
 1081            {
 25031082                string action = request.Headers.Action;
 25031083                if (action == null)
 1084                {
 01085                    action = MessageHeaders.WildcardAction;
 1086                }
 25031087                DispatchOperationRuntime operation = (DispatchOperationRuntime)_map[action];
 25031088                if (operation != null)
 1089                {
 24881090                    return operation;
 1091                }
 1092
 151093                return _unhandled;
 1094            }
 1095        }
 1096
 1097        private class CustomDemuxer : IDemuxer
 1098        {
 1099            private readonly Dictionary<string, DispatchOperationRuntime> _map;
 1100            private readonly IDispatchOperationSelector _selector;
 1101            private DispatchOperationRuntime _unhandled;
 1102
 381103            internal CustomDemuxer(IDispatchOperationSelector selector)
 1104            {
 381105                _selector = selector;
 381106                _map = new Dictionary<string, DispatchOperationRuntime>();
 381107            }
 1108
 1109            internal void Add(string name, DispatchOperationRuntime operation)
 1110            {
 1691111                _map.Add(name, operation);
 1691112            }
 1113
 1114            internal void SetUnhandled(DispatchOperationRuntime operation)
 1115            {
 381116                _unhandled = operation;
 381117            }
 1118
 1119            public DispatchOperationRuntime GetOperation(ref Message request)
 1120            {
 361121                string operationName = _selector.SelectOperation(ref request);
 351122                if (_map.TryGetValue(operationName, out DispatchOperationRuntime operation))
 1123                {
 351124                    return operation;
 1125                }
 1126                else
 1127                {
 01128                    return _unhandled;
 1129                }
 1130            }
 1131        }
 1132    }
 1133}

Methods/Properties

.ctor(CoreWCF.Dispatcher.DispatchRuntime)
CallContextCorrelationOffset()
CorrelationCount()
EnableFaults()
InstanceBehavior()
IsImpersonationEnabledOnSerializingReply()
RequireClaimsPrincipalOnOperationContext()
SupportsAuthorizationData()
ManualAddressing()
ParameterInspectorCorrelationOffset()
SecurityImpersonation()
ValidateMustUnderstand()
ErrorBehavior()
AcquireDynamicInstanceContextAsync(CoreWCF.Dispatcher.MessageRpc)
AcquireDynamicInstanceContextCoreAsync(CoreWCF.Dispatcher.MessageRpc)
AfterReceiveRequest(CoreWCF.Dispatcher.MessageRpc&)
AfterReceiveRequestCore(CoreWCF.Dispatcher.MessageRpc&)
BeforeSendReply(CoreWCF.Dispatcher.MessageRpc,System.Exception&,System.Boolean&)
BeforeSendReplyCore(CoreWCF.Dispatcher.MessageRpc,System.Exception&,System.Boolean&)
ReplyAsync()
DispatchAsync(CoreWCF.Dispatcher.MessageRpc,System.Boolean)
InputSessionDoneReceiving(CoreWCF.Channels.ServiceChannel)
InputSessionDoneReceivingCore(CoreWCF.Channels.ServiceChannel)
IsConcurrent(CoreWCF.Dispatcher.MessageRpc)
InputSessionFaulted(CoreWCF.Channels.ServiceChannel)
InputSessionFaultedCore(CoreWCF.Channels.ServiceChannel)
AddMessageProperties(CoreWCF.Channels.Message,CoreWCF.OperationContext,CoreWCF.Channels.ServiceChannel)
PrepareReplyAsync()
PrepareAndAddressReply(CoreWCF.Dispatcher.MessageRpc&)
GetOperation(CoreWCF.Channels.Message&)
ReceiveContextRPCFacet_CreatIfRequired_Shim(CoreWCF.Dispatcher.MessageRpc)
ProcessMessageAsync()
CreateActivity(CoreWCF.Channels.Message&,CoreWCF.IClientChannel,CoreWCF.InstanceContext)
ProcessError()
GetActionMetadata(CoreWCF.Channels.Message,System.String)
ProcessMessageCleanupAsync()
ProcessMessageNonCleanupError()
ProcessMessageCleanupError(CoreWCF.Dispatcher.MessageRpc)
SetActivityIdOnThread(CoreWCF.Dispatcher.MessageRpc)
TransferChannelFromPendingList(CoreWCF.Dispatcher.MessageRpc)
.ctor()
Add(System.String,CoreWCF.Dispatcher.DispatchOperationRuntime)
SetUnhandled(CoreWCF.Dispatcher.DispatchOperationRuntime)
GetOperation(CoreWCF.Channels.Message&)
.ctor(CoreWCF.Dispatcher.IDispatchOperationSelector)
Add(System.String,CoreWCF.Dispatcher.DispatchOperationRuntime)
SetUnhandled(CoreWCF.Dispatcher.DispatchOperationRuntime)
GetOperation(CoreWCF.Channels.Message&)