| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Dispatcher
- {
- using System;
- using System.Collections.Generic;
- using System.Collections.Specialized;
- using System.Diagnostics;
- using System.Runtime;
- using System.ServiceModel;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Diagnostics;
- using System.Threading;
- using System.Transactions;
- using System.ServiceModel.Diagnostics.Application;
- using System.Runtime.Diagnostics;
- using System.Security;
- class ImmutableDispatchRuntime
- {
- readonly AuthenticationBehavior authenticationBehavior;
- readonly AuthorizationBehavior authorizationBehavior;
- readonly int correlationCount;
- readonly ConcurrencyBehavior concurrency;
- readonly IDemuxer demuxer;
- readonly ErrorBehavior error;
- readonly bool enableFaults;
- readonly bool ignoreTransactionFlow;
- readonly bool impersonateOnSerializingReply;
- readonly IInputSessionShutdown[] inputSessionShutdownHandlers;
- readonly InstanceBehavior instance;
- readonly bool isOnServer;
- readonly bool manualAddressing;
- readonly IDispatchMessageInspector[] messageInspectors;
- readonly int parameterInspectorCorrelationOffset;
- readonly IRequestReplyCorrelator requestReplyCorrelator;
- readonly SecurityImpersonationBehavior securityImpersonation;
- readonly TerminatingOperationBehavior terminate;
- readonly ThreadBehavior thread;
- readonly TransactionBehavior transaction;
- readonly bool validateMustUnderstand;
- readonly bool receiveContextEnabledChannel;
- readonly bool sendAsynchronously;
- readonly bool requireClaimsPrincipalOnOperationContext;
- readonly MessageRpcProcessor processMessage1;
- readonly MessageRpcProcessor processMessage11;
- readonly MessageRpcProcessor processMessage2;
- readonly MessageRpcProcessor processMessage3;
- readonly MessageRpcProcessor processMessage31;
- readonly MessageRpcProcessor processMessage4;
- readonly MessageRpcProcessor processMessage41;
- readonly MessageRpcProcessor processMessage5;
- readonly MessageRpcProcessor processMessage6;
- readonly MessageRpcProcessor processMessage7;
- readonly MessageRpcProcessor processMessage8;
- readonly MessageRpcProcessor processMessage9;
- readonly MessageRpcProcessor processMessageCleanup;
- readonly MessageRpcProcessor processMessageCleanupError;
- static AsyncCallback onFinalizeCorrelationCompleted =
- Fx.ThunkCallback(new AsyncCallback(OnFinalizeCorrelationCompletedCallback));
- static AsyncCallback onReplyCompleted =
- Fx.ThunkCallback(new AsyncCallback(OnReplyCompletedCallback));
- bool didTraceProcessMessage1 = false;
- bool didTraceProcessMessage2 = false;
- bool didTraceProcessMessage3 = false;
- bool didTraceProcessMessage31 = false;
- bool didTraceProcessMessage4 = false;
- bool didTraceProcessMessage41 = false;
- internal ImmutableDispatchRuntime(DispatchRuntime dispatch)
- {
- this.authenticationBehavior = AuthenticationBehavior.TryCreate(dispatch);
- this.authorizationBehavior = AuthorizationBehavior.TryCreate(dispatch);
- this.concurrency = new ConcurrencyBehavior(dispatch);
- this.error = new ErrorBehavior(dispatch.ChannelDispatcher);
- this.enableFaults = dispatch.EnableFaults;
- this.inputSessionShutdownHandlers = EmptyArray<IInputSessionShutdown>.ToArray(dispatch.InputSessionShutdownHandlers);
- this.instance = new InstanceBehavior(dispatch, this);
- this.isOnServer = dispatch.IsOnServer;
- this.manualAddressing = dispatch.ManualAddressing;
- this.messageInspectors = EmptyArray<IDispatchMessageInspector>.ToArray(dispatch.MessageInspectors);
- this.requestReplyCorrelator = new RequestReplyCorrelator();
- this.securityImpersonation = SecurityImpersonationBehavior.CreateIfNecessary(dispatch);
- this.requireClaimsPrincipalOnOperationContext = dispatch.RequireClaimsPrincipalOnOperationContext;
- this.impersonateOnSerializingReply = dispatch.ImpersonateOnSerializingReply;
- this.terminate = TerminatingOperationBehavior.CreateIfNecessary(dispatch);
- this.thread = new ThreadBehavior(dispatch);
- this.validateMustUnderstand = dispatch.ValidateMustUnderstand;
- this.ignoreTransactionFlow = dispatch.IgnoreTransactionMessageProperty;
- this.transaction = TransactionBehavior.CreateIfNeeded(dispatch);
- this.receiveContextEnabledChannel = dispatch.ChannelDispatcher.ReceiveContextEnabled;
- this.sendAsynchronously = dispatch.ChannelDispatcher.SendAsynchronously;
- this.parameterInspectorCorrelationOffset = (dispatch.MessageInspectors.Count +
- dispatch.MaxCallContextInitializers);
- this.correlationCount = this.parameterInspectorCorrelationOffset + dispatch.MaxParameterInspectors;
- DispatchOperationRuntime unhandled = new DispatchOperationRuntime(dispatch.UnhandledDispatchOperation, this);
- if (dispatch.OperationSelector == null)
- {
- ActionDemuxer demuxer = new ActionDemuxer();
- for (int i = 0; i < dispatch.Operations.Count; i++)
- {
- DispatchOperation operation = dispatch.Operations[i];
- DispatchOperationRuntime operationRuntime = new DispatchOperationRuntime(operation, this);
- demuxer.Add(operation.Action, operationRuntime);
- }
- demuxer.SetUnhandled(unhandled);
- this.demuxer = demuxer;
- }
- else
- {
- CustomDemuxer demuxer = new CustomDemuxer(dispatch.OperationSelector);
- for (int i = 0; i < dispatch.Operations.Count; i++)
- {
- DispatchOperation operation = dispatch.Operations[i];
- DispatchOperationRuntime operationRuntime = new DispatchOperationRuntime(operation, this);
- demuxer.Add(operation.Name, operationRuntime);
- }
- demuxer.SetUnhandled(unhandled);
- this.demuxer = demuxer;
- }
- this.processMessage1 = new MessageRpcProcessor(this.ProcessMessage1);
- this.processMessage11 = new MessageRpcProcessor(this.ProcessMessage11);
- this.processMessage2 = new MessageRpcProcessor(this.ProcessMessage2);
- this.processMessage3 = new MessageRpcProcessor(this.ProcessMessage3);
- this.processMessage31 = new MessageRpcProcessor(this.ProcessMessage31);
- this.processMessage4 = new MessageRpcProcessor(this.ProcessMessage4);
- this.processMessage41 = new MessageRpcProcessor(this.ProcessMessage41);
- this.processMessage5 = new MessageRpcProcessor(this.ProcessMessage5);
- this.processMessage6 = new MessageRpcProcessor(this.ProcessMessage6);
- this.processMessage7 = new MessageRpcProcessor(this.ProcessMessage7);
- this.processMessage8 = new MessageRpcProcessor(this.ProcessMessage8);
- this.processMessage9 = new MessageRpcProcessor(this.ProcessMessage9);
- this.processMessageCleanup = new MessageRpcProcessor(this.ProcessMessageCleanup);
- this.processMessageCleanupError = new MessageRpcProcessor(this.ProcessMessageCleanupError);
- }
- internal int CallContextCorrelationOffset
- {
- get { return this.messageInspectors.Length; }
- }
- internal int CorrelationCount
- {
- get { return this.correlationCount; }
- }
- internal bool EnableFaults
- {
- get { return this.enableFaults; }
- }
- internal InstanceBehavior InstanceBehavior
- {
- get { return this.instance; }
- }
- internal bool IsImpersonationEnabledOnSerializingReply
- {
- get { return this.impersonateOnSerializingReply; }
- }
- internal bool RequireClaimsPrincipalOnOperationContext
- {
- get { return this.requireClaimsPrincipalOnOperationContext; }
- }
- internal bool ManualAddressing
- {
- get { return this.manualAddressing; }
- }
- internal int MessageInspectorCorrelationOffset
- {
- get { return 0; }
- }
- internal int ParameterInspectorCorrelationOffset
- {
- get { return this.parameterInspectorCorrelationOffset; }
- }
- internal IRequestReplyCorrelator RequestReplyCorrelator
- {
- get { return this.requestReplyCorrelator; }
- }
- internal SecurityImpersonationBehavior SecurityImpersonation
- {
- get { return this.securityImpersonation; }
- }
- internal bool ValidateMustUnderstand
- {
- get { return validateMustUnderstand; }
- }
- internal ErrorBehavior ErrorBehavior
- {
- get { return this.error; }
- }
- bool AcquireDynamicInstanceContext(ref MessageRpc rpc)
- {
- if (rpc.InstanceContext.QuotaThrottle != null)
- {
- return AcquireDynamicInstanceContextCore(ref rpc);
- }
- else
- {
- return true;
- }
- }
- bool AcquireDynamicInstanceContextCore(ref MessageRpc rpc)
- {
- bool success = rpc.InstanceContext.QuotaThrottle.Acquire(rpc.Pause());
- if (success)
- {
- rpc.UnPause();
- }
- return success;
- }
- internal void AfterReceiveRequest(ref MessageRpc rpc)
- {
- if (this.messageInspectors.Length > 0)
- {
- AfterReceiveRequestCore(ref rpc);
- }
- }
- internal void AfterReceiveRequestCore(ref MessageRpc rpc)
- {
- int offset = this.MessageInspectorCorrelationOffset;
- try
- {
- for (int i = 0; i < this.messageInspectors.Length; i++)
- {
- rpc.Correlation[offset + i] = this.messageInspectors[i].AfterReceiveRequest(ref rpc.Request, (IClientChannel)rpc.Channel.Proxy, rpc.InstanceContext);
- if (TD.MessageInspectorAfterReceiveInvokedIsEnabled())
- {
- TD.MessageInspectorAfterReceiveInvoked(rpc.EventTraceActivity, this.messageInspectors[i].GetType().FullName);
- }
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (ErrorBehavior.ShouldRethrowExceptionAsIs(e))
- {
- throw;
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
- }
- }
- void BeforeSendReply(ref MessageRpc rpc, ref Exception exception, ref bool thereIsAnUnhandledException)
- {
- if (this.messageInspectors.Length > 0)
- {
- BeforeSendReplyCore(ref rpc, ref exception, ref thereIsAnUnhandledException);
- }
- }
- internal void BeforeSendReplyCore(ref MessageRpc rpc, ref Exception exception, ref bool thereIsAnUnhandledException)
- {
- int offset = this.MessageInspectorCorrelationOffset;
- for (int i = 0; i < this.messageInspectors.Length; i++)
- {
- try
- {
- Message originalReply = rpc.Reply;
- Message reply = originalReply;
- this.messageInspectors[i].BeforeSendReply(ref reply, rpc.Correlation[offset + i]);
- if (TD.MessageInspectorBeforeSendInvokedIsEnabled())
- {
- TD.MessageInspectorBeforeSendInvoked(rpc.EventTraceActivity, this.messageInspectors[i].GetType().FullName);
- }
- if ((reply == null) && (originalReply != null))
- {
- string message = SR.GetString(SR.SFxNullReplyFromExtension2, this.messageInspectors[i].GetType().ToString(), (rpc.Operation.Name ?? ""));
- ErrorBehavior.ThrowAndCatch(new InvalidOperationException(message));
- }
- rpc.Reply = reply;
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (!ErrorBehavior.ShouldRethrowExceptionAsIs(e))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
- }
- if (exception == null)
- {
- exception = e;
- }
- thereIsAnUnhandledException = (!this.error.HandleError(e)) || thereIsAnUnhandledException;
- }
- }
- }
- void FinalizeCorrelation(ref MessageRpc rpc)
- {
- Message reply = rpc.Reply;
- if (reply != null && rpc.Error == null)
- {
- if (rpc.transaction != null && rpc.transaction.Current != null &&
- rpc.transaction.Current.TransactionInformation.Status != TransactionStatus.Active)
- {
- return;
- }
- CorrelationCallbackMessageProperty callback;
- if (CorrelationCallbackMessageProperty.TryGet(reply, out callback))
- {
- if (callback.IsFullyDefined)
- {
- try
- {
- rpc.RequestContextThrewOnReply = true;
- rpc.CorrelationCallback = callback;
- rpc.Reply = rpc.CorrelationCallback.FinalizeCorrelation(reply,
- rpc.ReplyTimeoutHelper.RemainingTime());
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (!this.error.HandleError(e))
- {
- rpc.CorrelationCallback = null;
- rpc.CanSendReply = false;
- }
- }
- }
- else
- {
- rpc.CorrelationCallback = new RpcCorrelationCallbackMessageProperty(callback, this, ref rpc);
- reply.Properties[CorrelationCallbackMessageProperty.Name] = rpc.CorrelationCallback;
- }
- }
- }
- }
- void BeginFinalizeCorrelation(ref MessageRpc rpc)
- {
- Message reply = rpc.Reply;
- if (reply != null && rpc.Error == null)
- {
- if (rpc.transaction != null && rpc.transaction.Current != null &&
- rpc.transaction.Current.TransactionInformation.Status != TransactionStatus.Active)
- {
- return;
- }
- CorrelationCallbackMessageProperty callback;
- if (CorrelationCallbackMessageProperty.TryGet(reply, out callback))
- {
- if (callback.IsFullyDefined)
- {
- bool success = false;
- try
- {
- rpc.RequestContextThrewOnReply = true;
- rpc.CorrelationCallback = callback;
- IResumeMessageRpc resume = rpc.Pause();
- rpc.AsyncResult = rpc.CorrelationCallback.BeginFinalizeCorrelation(reply,
- rpc.ReplyTimeoutHelper.RemainingTime(), onFinalizeCorrelationCompleted, resume);
- success = true;
- if (rpc.AsyncResult.CompletedSynchronously)
- {
- rpc.UnPause();
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (!this.error.HandleError(e))
- {
- rpc.CorrelationCallback = null;
- rpc.CanSendReply = false;
- }
- }
- finally
- {
- if (!success)
- {
- rpc.UnPause();
- }
- }
- }
- else
- {
- rpc.CorrelationCallback = new RpcCorrelationCallbackMessageProperty(callback, this, ref rpc);
- reply.Properties[CorrelationCallbackMessageProperty.Name] = rpc.CorrelationCallback;
- }
- }
- }
- }
- void Reply(ref MessageRpc rpc)
- {
- rpc.RequestContextThrewOnReply = true;
- rpc.SuccessfullySendReply = false;
- try
- {
- rpc.RequestContext.Reply(rpc.Reply, rpc.ReplyTimeoutHelper.RemainingTime());
- rpc.RequestContextThrewOnReply = false;
- rpc.SuccessfullySendReply = true;
- if (TD.DispatchMessageStopIsEnabled())
- {
- TD.DispatchMessageStop(rpc.EventTraceActivity);
- }
- }
- catch (CommunicationException e)
- {
- this.error.HandleError(e);
- }
- catch (TimeoutException e)
- {
- this.error.HandleError(e);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (DiagnosticUtility.ShouldTraceError)
- {
- TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.ServiceOperationExceptionOnReply,
- SR.GetString(SR.TraceCodeServiceOperationExceptionOnReply),
- this, e);
- }
- if (!this.error.HandleError(e))
- {
- rpc.RequestContextThrewOnReply = true;
- rpc.CanSendReply = false;
- }
- }
- }
- void BeginReply(ref MessageRpc rpc)
- {
- bool success = false;
- try
- {
- IResumeMessageRpc resume = rpc.Pause();
- rpc.AsyncResult = rpc.RequestContext.BeginReply(rpc.Reply, rpc.ReplyTimeoutHelper.RemainingTime(),
- onReplyCompleted, resume);
- success = true;
- if (rpc.AsyncResult.CompletedSynchronously)
- {
- rpc.UnPause();
- }
- }
- catch (CommunicationException e)
- {
- this.error.HandleError(e);
- }
- catch (TimeoutException e)
- {
- this.error.HandleError(e);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (DiagnosticUtility.ShouldTraceError)
- {
- TraceUtility.TraceEvent(System.Diagnostics.TraceEventType.Error,
- TraceCode.ServiceOperationExceptionOnReply,
- SR.GetString(SR.TraceCodeServiceOperationExceptionOnReply),
- this, e);
- }
- if (!this.error.HandleError(e))
- {
- rpc.RequestContextThrewOnReply = true;
- rpc.CanSendReply = false;
- }
- }
- finally
- {
- if (!success)
- {
- rpc.UnPause();
- }
- }
- }
- internal bool Dispatch(ref MessageRpc rpc, bool isOperationContextSet)
- {
- rpc.ErrorProcessor = this.processMessage8;
- rpc.NextProcessor = this.processMessage1;
- return rpc.Process(isOperationContextSet);
- }
- void EndFinalizeCorrelation(ref MessageRpc rpc)
- {
- try
- {
- rpc.Reply = rpc.CorrelationCallback.EndFinalizeCorrelation(rpc.AsyncResult);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (!this.error.HandleError(e))
- {
- rpc.CanSendReply = false;
- }
- }
- }
- bool EndReply(ref MessageRpc rpc)
- {
- bool success = false;
- try
- {
- rpc.RequestContext.EndReply(rpc.AsyncResult);
- rpc.RequestContextThrewOnReply = false;
- success = true;
- if (TD.DispatchMessageStopIsEnabled())
- {
- TD.DispatchMessageStop(rpc.EventTraceActivity);
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- this.error.HandleError(e);
- }
- return success;
- }
- internal void InputSessionDoneReceiving(ServiceChannel channel)
- {
- if (this.inputSessionShutdownHandlers.Length > 0)
- {
- this.InputSessionDoneReceivingCore(channel);
- }
- }
- void InputSessionDoneReceivingCore(ServiceChannel channel)
- {
- IDuplexContextChannel proxy = channel.Proxy as IDuplexContextChannel;
- if (proxy != null)
- {
- IInputSessionShutdown[] handlers = this.inputSessionShutdownHandlers;
- try
- {
- for (int i = 0; i < handlers.Length; i++)
- {
- handlers[i].DoneReceiving(proxy);
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (!this.error.HandleError(e))
- {
- proxy.Abort();
- }
- }
- }
- }
- internal bool IsConcurrent(ref MessageRpc rpc)
- {
- return this.concurrency.IsConcurrent(ref rpc);
- }
- internal void InputSessionFaulted(ServiceChannel channel)
- {
- if (this.inputSessionShutdownHandlers.Length > 0)
- {
- this.InputSessionFaultedCore(channel);
- }
- }
- void InputSessionFaultedCore(ServiceChannel channel)
- {
- IDuplexContextChannel proxy = channel.Proxy as IDuplexContextChannel;
- if (proxy != null)
- {
- IInputSessionShutdown[] handlers = this.inputSessionShutdownHandlers;
- try
- {
- for (int i = 0; i < handlers.Length; i++)
- {
- handlers[i].ChannelFaulted(proxy);
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (!this.error.HandleError(e))
- {
- proxy.Abort();
- }
- }
- }
- }
- static internal void GotDynamicInstanceContext(object state)
- {
- bool alreadyResumedNoLock;
- ((IResumeMessageRpc)state).Resume(out alreadyResumedNoLock);
- if (alreadyResumedNoLock)
- {
- Fx.Assert("GotDynamicInstanceContext more than once for same call.");
- }
- }
- void AddMessageProperties(Message message, OperationContext context, ServiceChannel replyChannel)
- {
- if (context.InternalServiceChannel == replyChannel)
- {
- if (context.HasOutgoingMessageHeaders)
- {
- message.Headers.CopyHeadersFrom(context.OutgoingMessageHeaders);
- }
- if (context.HasOutgoingMessageProperties)
- {
- message.Properties.MergeProperties(context.OutgoingMessageProperties);
- }
- }
- }
- static void OnFinalizeCorrelationCompletedCallback(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- IResumeMessageRpc resume = result.AsyncState as IResumeMessageRpc;
- if (resume == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxInvalidAsyncResultState0));
- }
- resume.Resume(result);
- }
- static void OnReplyCompletedCallback(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- IResumeMessageRpc resume = result.AsyncState as IResumeMessageRpc;
- if (resume == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxInvalidAsyncResultState0));
- }
- resume.Resume(result);
- }
- void PrepareReply(ref MessageRpc rpc)
- {
- RequestContext context = rpc.OperationContext.RequestContext;
- Exception exception = null;
- bool thereIsAnUnhandledException = false;
- if (!rpc.Operation.IsOneWay)
- {
- if (DiagnosticUtility.ShouldTraceWarning)
- {
- // If a service both returns null and sets RequestContext null, that
- // means they handled it (either by calling Close or Reply manually).
- // These traces catch accidents, where you accidentally return null,
- // or you accidentally close the context so we can't return your message.
- if ((rpc.Reply == null) && (context != null))
- {
- TraceUtility.TraceEvent(System.Diagnostics.TraceEventType.Warning,
- TraceCode.ServiceOperationMissingReply,
- SR.GetString(SR.TraceCodeServiceOperationMissingReply, rpc.Operation.Name ?? String.Empty),
- null, null);
- }
- else if ((context == null) && (rpc.Reply != null))
- {
- TraceUtility.TraceEvent(System.Diagnostics.TraceEventType.Warning,
- TraceCode.ServiceOperationMissingReplyContext,
- SR.GetString(SR.TraceCodeServiceOperationMissingReplyContext, rpc.Operation.Name ?? String.Empty),
- null, null);
- }
- }
- if ((context != null) && (rpc.Reply != null))
- {
- try
- {
- rpc.CanSendReply = PrepareAndAddressReply(ref rpc);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- thereIsAnUnhandledException = (!this.error.HandleError(e)) || thereIsAnUnhandledException;
- exception = e;
- }
- }
- }
- this.BeforeSendReply(ref rpc, ref exception, ref thereIsAnUnhandledException);
- if (rpc.Operation.IsOneWay)
- {
- rpc.CanSendReply = false;
- }
- if (!rpc.Operation.IsOneWay && (context != null) && (rpc.Reply != null))
- {
- if (exception != null)
- {
- // We don't call ProvideFault again, since we have already passed the
- // point where SFx addresses the reply, and it is reasonable for
- // ProvideFault to expect that SFx will address the reply. Instead
- // we always just do 'internal server error' processing.
- rpc.Error = exception;
- this.error.ProvideOnlyFaultOfLastResort(ref rpc);
- try
- {
- rpc.CanSendReply = PrepareAndAddressReply(ref rpc);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- this.error.HandleError(e);
- }
- }
- }
- else if ((exception != null) && thereIsAnUnhandledException)
- {
- rpc.Abort();
- }
- }
- bool PrepareAndAddressReply(ref MessageRpc rpc)
- {
- bool canSendReply = true;
- if (!this.manualAddressing)
- {
- if (!object.ReferenceEquals(rpc.RequestID, null))
- {
- System.ServiceModel.Channels.RequestReplyCorrelator.PrepareReply(rpc.Reply, rpc.RequestID);
- }
- if (!rpc.Channel.HasSession)
- {
- canSendReply = System.ServiceModel.Channels.RequestReplyCorrelator.AddressReply(rpc.Reply, rpc.ReplyToInfo);
- }
- }
- AddMessageProperties(rpc.Reply, rpc.OperationContext, rpc.Channel);
- if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled && rpc.EventTraceActivity != null)
- {
- rpc.Reply.Properties[EventTraceActivity.Name] = rpc.EventTraceActivity;
- }
- return canSendReply;
- }
- internal DispatchOperationRuntime GetOperation(ref Message message)
- {
- return this.demuxer.GetOperation(ref message);
- }
- internal void ProcessMessage1(ref MessageRpc rpc)
- {
- rpc.NextProcessor = this.processMessage11;
- if (this.receiveContextEnabledChannel)
- {
- ReceiveContextRPCFacet.CreateIfRequired(this, ref rpc);
- }
- if (!rpc.IsPaused)
- {
- this.ProcessMessage11(ref rpc);
- }
- else if (this.isOnServer && DiagnosticUtility.ShouldTraceInformation && !this.didTraceProcessMessage1)
- {
- this.didTraceProcessMessage1 = true;
- TraceUtility.TraceEvent(
- TraceEventType.Information,
- TraceCode.MessageProcessingPaused,
- SR.GetString(SR.TraceCodeProcessMessage31Paused,
- rpc.Channel.DispatchRuntime.EndpointDispatcher.ContractName,
- rpc.Channel.DispatchRuntime.EndpointDispatcher.EndpointAddress));
- }
- }
- internal void ProcessMessage11(ref MessageRpc rpc)
- {
- rpc.NextProcessor = this.processMessage2;
- if (rpc.Operation.IsOneWay)
- {
- rpc.RequestContext.Reply(null);
- rpc.OperationContext.RequestContext = null;
- }
- else
- {
- if (!rpc.Channel.IsReplyChannel &&
- ((object)rpc.RequestID == null) &&
- (rpc.Operation.Action != MessageHeaders.WildcardAction))
- {
- CommunicationException error = new CommunicationException(SR.GetString(SR.SFxOneWayMessageToTwoWayMethod0));
- throw TraceUtility.ThrowHelperError(error, rpc.Request);
- }
- if (!this.manualAddressing)
- {
- EndpointAddress replyTo = rpc.ReplyToInfo.ReplyTo;
- if (replyTo != null && replyTo.IsNone && rpc.Channel.IsReplyChannel)
- {
- CommunicationException error = new CommunicationException(SR.GetString(SR.SFxRequestReplyNone));
- throw TraceUtility.ThrowHelperError(error, rpc.Request);
- }
- if (this.isOnServer)
- {
- EndpointAddress remoteAddress = rpc.Channel.RemoteAddress;
- if ((remoteAddress != null) && !remoteAddress.IsAnonymous)
- {
- MessageHeaders headers = rpc.Request.Headers;
- Uri remoteUri = remoteAddress.Uri;
- if ((replyTo != null) && !replyTo.IsAnonymous && (remoteUri != replyTo.Uri))
- {
- string text = SR.GetString(SR.SFxRequestHasInvalidReplyToOnServer, replyTo.Uri, remoteUri);
- Exception error = new InvalidOperationException(text);
- throw TraceUtility.ThrowHelperError(error, rpc.Request);
- }
- EndpointAddress faultTo = headers.FaultTo;
- if ((faultTo != null) && !faultTo.IsAnonymous && (remoteUri != faultTo.Uri))
- {
- string text = SR.GetString(SR.SFxRequestHasInvalidFaultToOnServer, faultTo.Uri, remoteUri);
- Exception error = new InvalidOperationException(text);
- throw TraceUtility.ThrowHelperError(error, rpc.Request);
- }
- if (rpc.RequestVersion.Addressing == AddressingVersion.WSAddressingAugust2004)
- {
- EndpointAddress from = headers.From;
- if ((from != null) && !from.IsAnonymous && (remoteUri != from.Uri))
- {
- string text = SR.GetString(SR.SFxRequestHasInvalidFromOnServer, from.Uri, remoteUri);
- Exception error = new InvalidOperationException(text);
- throw TraceUtility.ThrowHelperError(error, rpc.Request);
- }
- }
- }
- }
- }
- }
- if (this.concurrency.IsConcurrent(ref rpc))
- {
- rpc.Channel.IncrementActivity();
- rpc.SuccessfullyIncrementedActivity = true;
- }
- if (this.authenticationBehavior != null)
- {
- this.authenticationBehavior.Authenticate(ref rpc);
- }
- if (this.authorizationBehavior != null)
- {
- this.authorizationBehavior.Authorize(ref rpc);
- }
- this.instance.EnsureInstanceContext(ref rpc);
- this.TransferChannelFromPendingList(ref rpc);
- this.AcquireDynamicInstanceContext(ref rpc);
- if (!rpc.IsPaused)
- {
- this.ProcessMessage2(ref rpc);
- }
- }
- void ProcessMessage2(ref MessageRpc rpc)
- {
- rpc.NextProcessor = this.processMessage3;
- this.AfterReceiveRequest(ref rpc);
- if (!this.ignoreTransactionFlow)
- {
- // Transactions need to have the context in the message
- rpc.TransactionMessageProperty = TransactionMessageProperty.TryGet(rpc.Request);
- }
- this.concurrency.LockInstance(ref rpc);
- if (!rpc.IsPaused)
- {
- this.ProcessMessage3(ref rpc);
- }
- else if (this.isOnServer && DiagnosticUtility.ShouldTraceInformation && !this.didTraceProcessMessage2)
- {
- this.didTraceProcessMessage2 = true;
- TraceUtility.TraceEvent(
- TraceEventType.Information,
- TraceCode.MessageProcessingPaused,
- SR.GetString(SR.TraceCodeProcessMessage2Paused,
- rpc.Channel.DispatchRuntime.EndpointDispatcher.ContractName,
- rpc.Channel.DispatchRuntime.EndpointDispatcher.EndpointAddress));
- }
- }
- void ProcessMessage3(ref MessageRpc rpc)
- {
- rpc.NextProcessor = this.processMessage31;
- rpc.SuccessfullyLockedInstance = true;
- // This also needs to happen after LockInstance, in case
- // we are using an AutoComplete=false transaction.
- if (this.transaction != null)
- {
- this.transaction.ResolveTransaction(ref rpc);
- if (rpc.Operation.TransactionRequired)
- {
- this.transaction.SetCurrent(ref rpc);
- }
- }
- if (!rpc.IsPaused)
- {
- this.ProcessMessage31(ref rpc);
- }
- else if (this.isOnServer && DiagnosticUtility.ShouldTraceInformation && !this.didTraceProcessMessage3)
- {
- this.didTraceProcessMessage3 = true;
- TraceUtility.TraceEvent(
- TraceEventType.Information,
- TraceCode.MessageProcessingPaused,
- SR.GetString(SR.TraceCodeProcessMessage3Paused,
- rpc.Channel.DispatchRuntime.EndpointDispatcher.ContractName,
- rpc.Channel.DispatchRuntime.EndpointDispatcher.EndpointAddress));
- }
- }
- void ProcessMessage31(ref MessageRpc rpc)
- {
- rpc.NextProcessor = this.ProcessMessage4;
- if (this.transaction != null)
- {
- if (rpc.Operation.TransactionRequired)
- {
- ReceiveContextRPCFacet receiveContext = rpc.ReceiveContext;
- if (receiveContext != null)
- {
- rpc.ReceiveContext = null;
- receiveContext.Complete(this, ref rpc, TimeSpan.MaxValue, rpc.Transaction.Current);
- }
- }
- }
- if (!rpc.IsPaused)
- {
- this.ProcessMessage4(ref rpc);
- }
- else if (this.isOnServer && DiagnosticUtility.ShouldTraceInformation && !this.didTraceProcessMessage31)
- {
- this.didTraceProcessMessage31 = true;
- TraceUtility.TraceEvent(
- TraceEventType.Information,
- TraceCode.MessageProcessingPaused,
- SR.GetString(SR.TraceCodeProcessMessage31Paused,
- rpc.Channel.DispatchRuntime.EndpointDispatcher.ContractName,
- rpc.Channel.DispatchRuntime.EndpointDispatcher.EndpointAddress));
- }
- }
- void ProcessMessage4(ref MessageRpc rpc)
- {
- rpc.NextProcessor = this.processMessage41;
- try
- {
- this.thread.BindThread(ref rpc);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(e.Message, e);
- }
- if (!rpc.IsPaused)
- {
- this.ProcessMessage41(ref rpc);
- }
- else if (this.isOnServer && DiagnosticUtility.ShouldTraceInformation && !this.didTraceProcessMessage4)
- {
- this.didTraceProcessMessage4 = true;
- TraceUtility.TraceEvent(
- TraceEventType.Information,
- TraceCode.MessageProcessingPaused,
- SR.GetString(SR.TraceCodeProcessMessage4Paused,
- rpc.Channel.DispatchRuntime.EndpointDispatcher.ContractName,
- rpc.Channel.DispatchRuntime.EndpointDispatcher.EndpointAddress));
- }
- }
- void ProcessMessage41(ref MessageRpc rpc)
- {
- rpc.NextProcessor = this.processMessage5;
- // This needs to happen after LockInstance--LockInstance guarantees
- // in-order delivery, so we can't receive the next message until we
- // have acquired the lock.
- //
- // This also needs to happen after BindThread, since EricZ believes
- // that running on UI thread should guarantee in-order delivery if
- // the SynchronizationContext is single threaded.
- // Note: for IManualConcurrencyOperationInvoker, the invoke assumes full control over pumping.
- if (this.concurrency.IsConcurrent(ref rpc) && !(rpc.Operation.Invoker is IManualConcurrencyOperationInvoker))
- {
- rpc.EnsureReceive();
- }
- this.instance.EnsureServiceInstance(ref rpc);
- if (!rpc.IsPaused)
- {
- this.ProcessMessage5(ref rpc);
- }
- else if (this.isOnServer && DiagnosticUtility.ShouldTraceInformation && !this.didTraceProcessMessage41)
- {
- this.didTraceProcessMessage41 = true;
- TraceUtility.TraceEvent(
- TraceEventType.Information,
- TraceCode.MessageProcessingPaused,
- SR.GetString(SR.TraceCodeProcessMessage4Paused,
- rpc.Channel.DispatchRuntime.EndpointDispatcher.ContractName,
- rpc.Channel.DispatchRuntime.EndpointDispatcher.EndpointAddress));
- }
- }
- void ProcessMessage5(ref MessageRpc rpc)
- {
- rpc.NextProcessor = this.processMessage6;
- try
- {
- bool success = false;
- try
- {
- if (!rpc.Operation.IsSynchronous)
- {
- // If async call completes in [....], it tells us through the gate below
- rpc.PrepareInvokeContinueGate();
- }
- if (this.transaction != null)
- {
- this.transaction.InitializeCallContext(ref rpc);
- }
- SetActivityIdOnThread(ref rpc);
- rpc.Operation.InvokeBegin(ref rpc);
- success = true;
- }
- finally
- {
- try
- {
- try
- {
- if (this.transaction != null)
- {
- this.transaction.ClearCallContext(ref rpc);
- }
- }
- finally
- {
- if (!rpc.Operation.IsSynchronous && rpc.IsPaused)
- {
- // Check if the callback produced the async result and set it back on the RPC on this stack
- // and proceed only if the gate was signaled by the callback and completed synchronously
- if (rpc.UnlockInvokeContinueGate(out rpc.AsyncResult))
- {
- rpc.UnPause();
- }
- }
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (success && (rpc.Operation.IsSynchronous || !rpc.IsPaused))
- {
- throw;
- }
- this.error.HandleError(e);
- }
- }
- }
- catch
- {
- // This catch clause forces ClearCallContext to run prior to stackwalks exiting this frame.
- throw;
- }
- // Proceed if rpc is unpaused and invoke begin was successful.
- if (!rpc.IsPaused)
- {
- this.ProcessMessage6(ref rpc);
- }
- }
- void ProcessMessage6(ref MessageRpc rpc)
- {
- rpc.NextProcessor = (rpc.Operation.IsSynchronous) ?
- this.processMessage8 :
- this.processMessage7;
- try
- {
- this.thread.BindEndThread(ref rpc);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(e.Message, e);
- }
- if (!rpc.IsPaused)
- {
- if (rpc.Operation.IsSynchronous)
- {
- this.ProcessMessage8(ref rpc);
- }
- else
- {
- this.ProcessMessage7(ref rpc);
- }
- }
- }
- void ProcessMessage7(ref MessageRpc rpc)
- {
- rpc.NextProcessor = null;
- try
- {
- bool success = false;
- try
- {
- if (this.transaction != null)
- {
- this.transaction.InitializeCallContext(ref rpc);
- }
- rpc.Operation.InvokeEnd(ref rpc);
- success = true;
- }
- finally
- {
- try
- {
- if (this.transaction != null)
- {
- this.transaction.ClearCallContext(ref rpc);
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (success)
- {
- // Throw the transaction.ClearContextException only if
- // there isn't an exception on the thread already.
- throw;
- }
- this.error.HandleError(e);
- }
- }
- }
- catch
- {
- // Make sure user Exception filters are not run with bad call context
- throw;
- }
- // this never pauses
- this.ProcessMessage8(ref rpc);
- }
- void ProcessMessage8(ref MessageRpc rpc)
- {
- rpc.NextProcessor = this.processMessage9;
- try
- {
- this.error.ProvideMessageFault(ref rpc);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- this.error.HandleError(e);
- }
- this.PrepareReply(ref rpc);
- if (rpc.CanSendReply)
- {
- rpc.ReplyTimeoutHelper = new TimeoutHelper(rpc.Channel.OperationTimeout);
- if (this.sendAsynchronously)
- {
- this.BeginFinalizeCorrelation(ref rpc);
- }
- else
- {
- this.FinalizeCorrelation(ref rpc);
- }
- }
- if (!rpc.IsPaused)
- {
- this.ProcessMessage9(ref rpc);
- }
- }
- void ProcessMessage9(ref MessageRpc rpc)
- {
- rpc.NextProcessor = this.processMessageCleanup;
- if (rpc.FinalizeCorrelationImplicitly && this.sendAsynchronously)
- {
- this.EndFinalizeCorrelation(ref rpc);
- }
- if (rpc.CorrelationCallback == null || rpc.FinalizeCorrelationImplicitly)
- {
- this.ResolveTransactionOutcome(ref rpc);
- }
- if (rpc.CanSendReply)
- {
- if (rpc.Reply != null)
- {
- TraceUtility.MessageFlowAtMessageSent(rpc.Reply, rpc.EventTraceActivity);
- }
- if (this.sendAsynchronously)
- {
- this.BeginReply(ref rpc);
- }
- else
- {
- this.Reply(ref rpc);
- }
- }
- if (!rpc.IsPaused)
- {
- this.ProcessMessageCleanup(ref rpc);
- }
- }
- // Logic for knowing when to close stuff:
- //
- // ASSUMPTIONS:
- // Closing a stream over a message also closes the message.
- // Closing a message over a stream does not close the stream.
- // (OperationStreamProvider.ReleaseStream is no-op)
- //
- // This is a table of what should be disposed in what cases.
- // The rows represent the type of parameter to the method and
- // whether we are disposing parameters or not. The columns
- // are for the inputs vs. the outputs. The cells contain the
- // values that need to be Disposed. M^P means that exactly
- // one of the message and parameter needs to be disposed,
- // since they refer to the same object.
- //
- // Request Reply
- // Message | M or P | M or P
- // Dispose Stream | P | M and P
- // Params | M and P | M and P
- // | |
- // Message | none | none
- // NoDispose Stream | none | M
- // Params | M | M
- //
- // By choosing to dispose the parameter in both of the "M or P"
- // cases, the logic needed to generate this table is:
- //
- // CloseRequestMessage = IsParams
- // CloseRequestParams = rpc.Operation.DisposeParameters
- // CloseReplyMessage = rpc.Operation.SerializeReply
- // CloseReplyParams = rpc.Operation.DisposeParameters
- //
- // IsParams can be calculated based on whether the request
- // message was consumed after deserializing but before calling
- // the user. This is stored as rpc.DidDeserializeRequestBody.
- //
- void ProcessMessageCleanup(ref MessageRpc rpc)
- {
- Fx.Assert(
- !object.ReferenceEquals(rpc.ErrorProcessor, this.processMessageCleanupError),
- "ProcessMessageCleanup run twice on the same MessageRpc!");
- rpc.ErrorProcessor = this.processMessageCleanupError;
- bool replyWasSent = false;
- if (rpc.CanSendReply)
- {
- if (this.sendAsynchronously)
- {
- replyWasSent = this.EndReply(ref rpc);
- }
- else
- {
- replyWasSent = rpc.SuccessfullySendReply;
- }
- }
- try
- {
- try
- {
- if (rpc.DidDeserializeRequestBody)
- {
- rpc.Request.Close();
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- this.error.HandleError(e);
- }
- if (rpc.HostingProperty != null)
- {
- try
- {
- rpc.HostingProperty.Close();
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(e.Message, e);
- }
- }
- // for wf, wf owns the lifetime of the request message. So in that case, we should not dispose the inputs
- IManualConcurrencyOperationInvoker manualInvoker = rpc.Operation.Invoker as IManualConcurrencyOperationInvoker;
- rpc.DisposeParameters(manualInvoker != null && manualInvoker.OwnsFormatter); //Dispose all input/output/return parameters
- if (rpc.FaultInfo.IsConsideredUnhandled)
- {
- if (!replyWasSent)
- {
- rpc.AbortRequestContext();
- rpc.AbortChannel();
- }
- else
- {
- rpc.CloseRequestContext();
- rpc.CloseChannel();
- }
- rpc.AbortInstanceContext();
- }
- else
- {
- if (rpc.RequestContextThrewOnReply)
- {
- rpc.AbortRequestContext();
- }
- else
- {
- rpc.CloseRequestContext();
- }
- }
- if ((rpc.Reply != null) && (rpc.Reply != rpc.ReturnParameter))
- {
- try
- {
- rpc.Reply.Close();
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- this.error.HandleError(e);
- }
- }
- if ((rpc.FaultInfo.Fault != null) && (rpc.FaultInfo.Fault.State != MessageState.Closed))
- {
- // maybe ProvideFault gave a Message, but then BeforeSendReply replaced it
- // in that case, we need to close the one from ProvideFault
- try
- {
- rpc.FaultInfo.Fault.Close();
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- this.error.HandleError(e);
- }
- }
- try
- {
- rpc.OperationContext.FireOperationCompleted();
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
- }
- this.instance.AfterReply(ref rpc, this.error);
- if (rpc.SuccessfullyLockedInstance)
- {
- try
- {
- this.concurrency.UnlockInstance(ref rpc);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- Fx.Assert("Exceptions should be caught by callee");
- rpc.InstanceContext.FaultInternal();
- this.error.HandleError(e);
- }
- }
- if (this.terminate != null)
- {
- try
- {
- this.terminate.AfterReply(ref rpc);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- this.error.HandleError(e);
- }
- }
- if (rpc.SuccessfullyIncrementedActivity)
- {
- try
- {
- rpc.Channel.DecrementActivity();
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- this.error.HandleError(e);
- }
- }
- }
- finally
- {
- if (rpc.MessageRpcOwnsInstanceContextThrottle && rpc.channelHandler.InstanceContextServiceThrottle != null)
- {
- rpc.channelHandler.InstanceContextServiceThrottle.DeactivateInstanceContext();
- }
- if (rpc.Activity != null && DiagnosticUtility.ShouldUseActivity)
- {
- rpc.Activity.Stop();
- }
- }
- this.error.HandleError(ref rpc);
- }
- void ProcessMessageCleanupError(ref MessageRpc rpc)
- {
- this.error.HandleError(ref rpc);
- }
- void ResolveTransactionOutcome(ref MessageRpc rpc)
- {
- if (this.transaction != null)
- {
- try
- {
- bool hadError = (rpc.Error != null);
- try
- {
- this.transaction.ResolveOutcome(ref rpc);
- }
- catch (FaultException e)
- {
- if (rpc.Error == null)
- {
- rpc.Error = e;
- }
- }
- finally
- {
- if (!hadError && rpc.Error != null)
- {
- this.error.ProvideMessageFault(ref rpc);
- this.PrepareAndAddressReply(ref rpc);
- }
- }
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- this.error.HandleError(e);
- }
- }
- }
- [Fx.Tag.SecurityNote(Critical = "Calls security critical method to set the ActivityId on the thread",
- Safe = "Set the ActivityId only when MessageRpc is available")]
- [SecuritySafeCritical]
- void SetActivityIdOnThread(ref MessageRpc rpc)
- {
- if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled && rpc.EventTraceActivity != null)
- {
- // Propogate the ActivityId to the service operation
- EventTraceActivityHelper.SetOnThread(rpc.EventTraceActivity);
- }
- }
- void TransferChannelFromPendingList(ref MessageRpc rpc)
- {
- if (rpc.Channel.IsPending)
- {
- rpc.Channel.IsPending = false;
- ChannelDispatcher channelDispatcher = rpc.Channel.ChannelDispatcher;
- IInstanceContextProvider provider = this.instance.InstanceContextProvider;
- if (!InstanceContextProviderBase.IsProviderSessionful(provider) &&
- !InstanceContextProviderBase.IsProviderSingleton(provider))
- {
- IChannel proxy = rpc.Channel.Proxy as IChannel;
- if (!rpc.InstanceContext.IncomingChannels.Contains(proxy))
- {
- channelDispatcher.Channels.Add(proxy);
- }
- }
- channelDispatcher.PendingChannels.Remove(rpc.Channel.Binder.Channel);
- }
- }
- interface IDemuxer
- {
- DispatchOperationRuntime GetOperation(ref Message request);
- }
- class ActionDemuxer : IDemuxer
- {
- HybridDictionary map;
- DispatchOperationRuntime unhandled;
- internal ActionDemuxer()
- {
- this.map = new HybridDictionary();
- }
- internal void Add(string action, DispatchOperationRuntime operation)
- {
- if (map.Contains(action))
- {
- DispatchOperationRuntime existingOperation = (DispatchOperationRuntime)map[action];
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxActionDemuxerDuplicate, existingOperation.Name, operation.Name, action)));
- }
- this.map.Add(action, operation);
- }
- internal void SetUnhandled(DispatchOperationRuntime operation)
- {
- this.unhandled = operation;
- }
- public DispatchOperationRuntime GetOperation(ref Message request)
- {
- string action = request.Headers.Action;
- if (action == null)
- {
- action = MessageHeaders.WildcardAction;
- }
- DispatchOperationRuntime operation = (DispatchOperationRuntime)this.map[action];
- if (operation != null)
- {
- return operation;
- }
- return this.unhandled;
- }
- }
- class CustomDemuxer : IDemuxer
- {
- Dictionary<string, DispatchOperationRuntime> map;
- IDispatchOperationSelector selector;
- DispatchOperationRuntime unhandled;
- internal CustomDemuxer(IDispatchOperationSelector selector)
- {
- this.selector = selector;
- this.map = new Dictionary<string, DispatchOperationRuntime>();
- }
- internal void Add(string name, DispatchOperationRuntime operation)
- {
- this.map.Add(name, operation);
- }
- internal void SetUnhandled(DispatchOperationRuntime operation)
- {
- this.unhandled = operation;
- }
- public DispatchOperationRuntime GetOperation(ref Message request)
- {
- string operationName = this.selector.SelectOperation(ref request);
- DispatchOperationRuntime operation = null;
- if (this.map.TryGetValue(operationName, out operation))
- {
- return operation;
- }
- else
- {
- return this.unhandled;
- }
- }
- }
- class RpcCorrelationCallbackMessageProperty : CorrelationCallbackMessageProperty
- {
- CorrelationCallbackMessageProperty innerCallback;
- MessageRpc rpc;
- ImmutableDispatchRuntime runtime;
- TransactionScope scope;
- // This constructor should be used when creating the RPCCorrelationMessageproperty the first time
- // Here we copy the data & the needed data from the original callback
- public RpcCorrelationCallbackMessageProperty(CorrelationCallbackMessageProperty innerCallback,
- ImmutableDispatchRuntime runtime, ref MessageRpc rpc)
- : base(innerCallback)
- {
- this.innerCallback = innerCallback;
- this.runtime = runtime;
- this.rpc = rpc;
- }
- // This constructor should be used when we are making a copy from the already initialized RPCCorrelationCallbackMessageProperty
- public RpcCorrelationCallbackMessageProperty(RpcCorrelationCallbackMessageProperty rpcCallbackMessageProperty)
- : base(rpcCallbackMessageProperty)
- {
- this.innerCallback = rpcCallbackMessageProperty.innerCallback;
- this.runtime = rpcCallbackMessageProperty.runtime;
- this.rpc = rpcCallbackMessageProperty.rpc;
- }
- public override IMessageProperty CreateCopy()
- {
- return new RpcCorrelationCallbackMessageProperty(this);
- }
- protected override IAsyncResult OnBeginFinalizeCorrelation(Message message, TimeSpan timeout,
- AsyncCallback callback, object state)
- {
- bool success = false;
- this.Enter();
- try
- {
- IAsyncResult result = this.innerCallback.BeginFinalizeCorrelation(message, timeout, callback, state);
- success = true;
- return result;
- }
- finally
- {
- this.Leave(success);
- }
- }
- protected override Message OnEndFinalizeCorrelation(IAsyncResult result)
- {
- bool success = false;
- this.Enter();
- try
- {
- Message message = this.innerCallback.EndFinalizeCorrelation(result);
- success = true;
- return message;
- }
- finally
- {
- this.Leave(success);
- this.CompleteTransaction();
- }
- }
- protected override Message OnFinalizeCorrelation(Message message, TimeSpan timeout)
- {
- bool success = false;
- this.Enter();
- try
- {
- Message newMessage = this.innerCallback.FinalizeCorrelation(message, timeout);
- success = true;
- return newMessage;
- }
- finally
- {
- this.Leave(success);
- this.CompleteTransaction();
- }
- }
- void CompleteTransaction()
- {
- this.runtime.ResolveTransactionOutcome(ref this.rpc);
- }
- void Enter()
- {
- if (this.rpc.transaction != null && this.rpc.transaction.Current != null)
- {
- this.scope = new TransactionScope(this.rpc.transaction.Current);
- }
- }
- void Leave(bool complete)
- {
- if (this.scope != null)
- {
- if (complete)
- {
- scope.Complete();
- }
- scope.Dispose();
- this.scope = null;
- }
- }
- }
- }
- }
|