1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //-----------------------------------------------------------------------------
5 namespace System.ServiceModel.Dispatcher
8 using System.Diagnostics;
9 using System.Globalization;
11 using System.Runtime.CompilerServices;
12 using System.Runtime.Diagnostics;
13 using System.ServiceModel;
14 using System.ServiceModel.Activation;
15 using System.ServiceModel.Channels;
16 using System.ServiceModel.Description;
17 using System.ServiceModel.Diagnostics;
18 using System.ServiceModel.Diagnostics.Application;
19 using System.Threading;
20 using System.Transactions;
22 using SessionIdleManager = System.ServiceModel.Channels.ServiceChannel.SessionIdleManager;
26 public static readonly TimeSpan CloseAfterFaultTimeout = TimeSpan.FromSeconds(10);
27 public const string MessageBufferPropertyName = "_RequestMessageBuffer_";
29 readonly IChannelBinder binder;
30 readonly DuplexChannelBinder duplexBinder;
31 readonly ServiceHostBase host;
32 readonly bool incrementedActivityCountInConstructor;
33 readonly bool isCallback;
34 readonly ListenerHandler listener;
35 readonly ServiceThrottle throttle;
36 readonly bool wasChannelThrottled;
37 readonly SessionIdleManager idleManager;
38 readonly bool sendAsynchronously;
40 static AsyncCallback onAsyncReplyComplete = Fx.ThunkCallback(new AsyncCallback(ChannelHandler.OnAsyncReplyComplete));
41 static AsyncCallback onAsyncReceiveComplete = Fx.ThunkCallback(new AsyncCallback(ChannelHandler.OnAsyncReceiveComplete));
42 static Action<object> onContinueAsyncReceive = new Action<object>(ChannelHandler.OnContinueAsyncReceive);
43 static Action<object> onStartSyncMessagePump = new Action<object>(ChannelHandler.OnStartSyncMessagePump);
44 static Action<object> onStartAsyncMessagePump = new Action<object>(ChannelHandler.OnStartAsyncMessagePump);
45 static Action<object> onStartSingleTransactedBatch = new Action<object>(ChannelHandler.OnStartSingleTransactedBatch);
46 static Action<object> openAndEnsurePump = new Action<object>(ChannelHandler.OpenAndEnsurePump);
48 RequestInfo requestInfo;
49 ServiceChannel channel;
51 bool hasRegisterBeenCalled;
54 bool isChannelTerminated;
56 bool isManualAddressing;
57 MessageVersion messageVersion;
58 ErrorHandlingReceiver receiver;
59 bool receiveSynchronously;
60 bool receiveWithTransaction;
61 RequestContext replied;
62 RequestContext requestWaitingForThrottle;
63 WrappedTransaction acceptTransaction;
64 ServiceThrottle instanceContextThrottle;
65 SharedTransactedBatchContext sharedTransactedBatchContext;
66 TransactedBatchContext transactedBatchContext;
67 bool isMainTransactedBatchHandler;
68 EventTraceActivity eventTraceActivity;
69 SessionOpenNotification sessionOpenNotification;
70 bool needToCreateSessionOpenNotificationMessage;
71 bool shouldRejectMessageWithOnOpenActionHeader;
73 internal ChannelHandler(MessageVersion messageVersion, IChannelBinder binder, ServiceChannel channel)
75 ClientRuntime clientRuntime = channel.ClientRuntime;
77 this.messageVersion = messageVersion;
78 this.isManualAddressing = clientRuntime.ManualAddressing;
80 this.channel = channel;
82 this.isConcurrent = true;
83 this.duplexBinder = binder as DuplexChannelBinder;
84 this.hasSession = binder.HasSession;
85 this.isCallback = true;
87 DispatchRuntime dispatchRuntime = clientRuntime.DispatchRuntime;
88 if (dispatchRuntime == null)
90 this.receiver = new ErrorHandlingReceiver(binder, null);
94 this.receiver = new ErrorHandlingReceiver(binder, dispatchRuntime.ChannelDispatcher);
96 this.requestInfo = new RequestInfo(this);
100 internal ChannelHandler(MessageVersion messageVersion, IChannelBinder binder, ServiceThrottle throttle,
101 ListenerHandler listener, bool wasChannelThrottled, WrappedTransaction acceptTransaction, SessionIdleManager idleManager)
103 ChannelDispatcher channelDispatcher = listener.ChannelDispatcher;
105 this.messageVersion = messageVersion;
106 this.isManualAddressing = channelDispatcher.ManualAddressing;
107 this.binder = binder;
108 this.throttle = throttle;
109 this.listener = listener;
110 this.wasChannelThrottled = wasChannelThrottled;
112 this.host = listener.Host;
113 this.receiveSynchronously = channelDispatcher.ReceiveSynchronously;
114 this.sendAsynchronously = channelDispatcher.SendAsynchronously;
115 this.duplexBinder = binder as DuplexChannelBinder;
116 this.hasSession = binder.HasSession;
117 this.isConcurrent = ConcurrencyBehavior.IsConcurrent(channelDispatcher, this.hasSession);
119 if (channelDispatcher.MaxPendingReceives > 1)
121 // We need to preserve order if the ChannelHandler is not concurrent.
122 this.binder = new MultipleReceiveBinder(
124 channelDispatcher.MaxPendingReceives,
128 if (channelDispatcher.BufferedReceiveEnabled)
130 this.binder = new BufferedReceiveBinder(this.binder);
133 this.receiver = new ErrorHandlingReceiver(this.binder, channelDispatcher);
134 this.idleManager = idleManager;
135 Fx.Assert((this.idleManager != null) == (this.binder.HasSession && this.listener.ChannelDispatcher.DefaultCommunicationTimeouts.ReceiveTimeout != TimeSpan.MaxValue), "idle manager is present only when there is a session with a finite receive timeout");
137 if (channelDispatcher.IsTransactedReceive && !channelDispatcher.ReceiveContextEnabled)
139 receiveSynchronously = true;
140 receiveWithTransaction = true;
142 if (channelDispatcher.MaxTransactedBatchSize > 0)
144 int maxConcurrentBatches = 1;
145 if (null != throttle && throttle.MaxConcurrentCalls > 1)
147 maxConcurrentBatches = throttle.MaxConcurrentCalls;
148 foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
150 if (ConcurrencyMode.Multiple != endpointDispatcher.DispatchRuntime.ConcurrencyMode)
152 maxConcurrentBatches = 1;
158 this.sharedTransactedBatchContext = new SharedTransactedBatchContext(this, channelDispatcher, maxConcurrentBatches);
159 this.isMainTransactedBatchHandler = true;
160 this.throttle = null;
163 else if (channelDispatcher.IsTransactedReceive && channelDispatcher.ReceiveContextEnabled && channelDispatcher.MaxTransactedBatchSize > 0)
165 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.IncompatibleBehaviors)));
168 if (this.binder.HasSession)
170 this.sessionOpenNotification = this.binder.Channel.GetProperty<SessionOpenNotification>();
171 this.needToCreateSessionOpenNotificationMessage = this.sessionOpenNotification != null && this.sessionOpenNotification.IsEnabled;
174 this.acceptTransaction = acceptTransaction;
175 this.requestInfo = new RequestInfo(this);
177 if (this.listener.State == CommunicationState.Opened)
179 this.listener.ChannelDispatcher.Channels.IncrementActivityCount();
180 this.incrementedActivityCountInConstructor = true;
185 internal ChannelHandler(ChannelHandler handler, TransactedBatchContext context)
187 this.messageVersion = handler.messageVersion;
188 this.isManualAddressing = handler.isManualAddressing;
189 this.binder = handler.binder;
190 this.listener = handler.listener;
191 this.wasChannelThrottled = handler.wasChannelThrottled;
193 this.host = handler.host;
194 this.receiveSynchronously = true;
195 this.receiveWithTransaction = true;
196 this.duplexBinder = handler.duplexBinder;
197 this.hasSession = handler.hasSession;
198 this.isConcurrent = handler.isConcurrent;
199 this.receiver = handler.receiver;
201 this.sharedTransactedBatchContext = context.Shared;
202 this.transactedBatchContext = context;
203 this.requestInfo = new RequestInfo(this);
205 this.sendAsynchronously = handler.sendAsynchronously;
206 this.sessionOpenNotification = handler.sessionOpenNotification;
207 this.needToCreateSessionOpenNotificationMessage = handler.needToCreateSessionOpenNotificationMessage;
208 this.shouldRejectMessageWithOnOpenActionHeader = handler.shouldRejectMessageWithOnOpenActionHeader;
211 internal IChannelBinder Binder
213 get { return this.binder; }
216 internal ServiceChannel Channel
218 get { return this.channel; }
221 internal bool HasRegisterBeenCalled
223 get { return this.hasRegisterBeenCalled; }
226 internal InstanceContext InstanceContext
228 get { return (this.channel != null) ? this.channel.InstanceContext : null; }
231 internal ServiceThrottle InstanceContextServiceThrottle
235 return this.instanceContextThrottle;
239 this.instanceContextThrottle = value;
245 get { return this.binder.Channel.State == CommunicationState.Opened; }
248 EndpointAddress LocalAddress
252 if (this.binder != null)
254 IInputChannel input = this.binder.Channel as IInputChannel;
257 return input.LocalAddress;
260 IReplyChannel reply = this.binder.Channel as IReplyChannel;
263 return reply.LocalAddress;
276 EventTraceActivity EventTraceActivity
280 if (this.eventTraceActivity == null)
282 this.eventTraceActivity = new EventTraceActivity();
284 return this.eventTraceActivity;
288 internal static void Register(ChannelHandler handler)
293 internal static void Register(ChannelHandler handler, RequestContext request)
295 BufferedReceiveBinder bufferedBinder = handler.Binder as BufferedReceiveBinder;
296 Fx.Assert(bufferedBinder != null, "ChannelHandler.Binder is not a BufferedReceiveBinder");
298 bufferedBinder.InjectRequest(request);
304 this.hasRegisterBeenCalled = true;
305 if (this.binder.Channel.State == CommunicationState.Created)
307 ActionItem.Schedule(openAndEnsurePump, this);
315 void AsyncMessagePump()
317 IAsyncResult result = this.BeginTryReceive();
319 if ((result != null) && result.CompletedSynchronously)
321 this.AsyncMessagePump(result);
325 void AsyncMessagePump(IAsyncResult result)
327 if (TD.ChannelReceiveStopIsEnabled())
329 TD.ChannelReceiveStop(this.EventTraceActivity, this.GetHashCode());
334 RequestContext request;
336 while (!this.EndTryReceive(result, out request))
338 result = this.BeginTryReceive();
340 if ((result == null) || !result.CompletedSynchronously)
346 if (!HandleRequest(request, null))
351 if (!TryAcquirePump())
356 result = this.BeginTryReceive();
358 if (result == null || !result.CompletedSynchronously)
365 IAsyncResult BeginTryReceive()
367 this.requestInfo.Cleanup();
369 if (TD.ChannelReceiveStartIsEnabled())
371 TD.ChannelReceiveStart(this.EventTraceActivity, this.GetHashCode());
374 this.shouldRejectMessageWithOnOpenActionHeader = !this.needToCreateSessionOpenNotificationMessage;
375 if (this.needToCreateSessionOpenNotificationMessage)
377 return new CompletedAsyncResult(ChannelHandler.onAsyncReceiveComplete, this);
380 return this.receiver.BeginTryReceive(TimeSpan.MaxValue, ChannelHandler.onAsyncReceiveComplete, this);
383 bool DispatchAndReleasePump(RequestContext request, bool cleanThread, OperationContext currentOperationContext)
385 ServiceChannel channel = this.requestInfo.Channel;
386 EndpointDispatcher endpoint = this.requestInfo.Endpoint;
387 bool releasedPump = false;
391 DispatchRuntime dispatchBehavior = this.requestInfo.DispatchRuntime;
393 if (channel == null || dispatchBehavior == null)
395 Fx.Assert("System.ServiceModel.Dispatcher.ChannelHandler.Dispatch(): (channel == null || dispatchBehavior == null)");
399 MessageBuffer buffer = null;
402 EventTraceActivity eventTraceActivity = TraceDispatchMessageStart(request.RequestMessage);
403 AspNetEnvironment.Current.PrepareMessageForDispatch(request.RequestMessage);
404 if (dispatchBehavior.PreserveMessage)
406 object previousBuffer = null;
407 if (request.RequestMessage.Properties.TryGetValue(MessageBufferPropertyName, out previousBuffer))
409 buffer = (MessageBuffer)previousBuffer;
410 message = buffer.CreateMessage();
415 buffer = request.RequestMessage.CreateBufferedCopy(int.MaxValue);
416 message = buffer.CreateMessage();
421 message = request.RequestMessage;
424 DispatchOperationRuntime operation = dispatchBehavior.GetOperation(ref message);
425 if (operation == null)
427 Fx.Assert("ChannelHandler.Dispatch (operation == null)");
428 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "No DispatchOperationRuntime found to process message.")));
431 if (this.shouldRejectMessageWithOnOpenActionHeader && message.Headers.Action == OperationDescription.SessionOpenedAction)
433 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoEndpointMatchingAddressForConnectionOpeningMessage, message.Headers.Action, "Open")));
436 if (MessageLogger.LoggingEnabled)
438 MessageLogger.LogMessage(ref message, (operation.IsOneWay ? MessageLoggingSource.ServiceLevelReceiveDatagram : MessageLoggingSource.ServiceLevelReceiveRequest) | MessageLoggingSource.LastChance);
441 if (operation.IsTerminating && this.hasSession)
443 this.isChannelTerminated = true;
446 bool hasOperationContextBeenSet;
447 if (currentOperationContext != null)
449 hasOperationContextBeenSet = true;
450 currentOperationContext.ReInit(request, message, channel);
454 hasOperationContextBeenSet = false;
455 currentOperationContext = new OperationContext(request, message, channel, this.host);
458 if (dispatchBehavior.PreserveMessage)
460 currentOperationContext.IncomingMessageProperties.Add(MessageBufferPropertyName, buffer);
463 if (currentOperationContext.EndpointDispatcher == null && this.listener != null)
465 currentOperationContext.EndpointDispatcher = endpoint;
468 MessageRpc rpc = new MessageRpc(request, message, operation, channel, this.host,
469 this, cleanThread, currentOperationContext, this.requestInfo.ExistingInstanceContext, eventTraceActivity);
471 TraceUtility.MessageFlowAtMessageReceived(message, currentOperationContext, eventTraceActivity, true);
473 rpc.TransactedBatchContext = this.transactedBatchContext;
475 // passing responsibility for call throttle to MessageRpc
476 // (MessageRpc implicitly owns this throttle once it's created)
477 this.requestInfo.ChannelHandlerOwnsCallThrottle = false;
478 // explicitly passing responsibility for instance throttle to MessageRpc
479 rpc.MessageRpcOwnsInstanceContextThrottle = this.requestInfo.ChannelHandlerOwnsInstanceContextThrottle;
480 this.requestInfo.ChannelHandlerOwnsInstanceContextThrottle = false;
482 // These need to happen before Dispatch but after accessing any ChannelHandler
483 // state, because we go multi-threaded after this until we reacquire pump mutex.
487 return operation.Parent.Dispatch(ref rpc, hasOperationContextBeenSet);
495 return this.HandleError(e, request, channel);
506 internal void DispatchDone()
508 if (this.throttle != null)
510 this.throttle.DeactivateCall();
514 RequestContext GetSessionOpenNotificationRequestContext()
516 Fx.Assert(this.sessionOpenNotification != null, "this.sessionOpenNotification should not be null.");
517 Message message = Message.CreateMessage(this.Binder.Channel.GetProperty<MessageVersion>(), OperationDescription.SessionOpenedAction);
518 Fx.Assert(this.LocalAddress != null, "this.LocalAddress should not be null.");
519 message.Headers.To = this.LocalAddress.Uri;
520 this.sessionOpenNotification.UpdateMessageProperties(message.Properties);
521 return this.Binder.CreateRequestContext(message);
524 bool EndTryReceive(IAsyncResult result, out RequestContext requestContext)
527 if (this.needToCreateSessionOpenNotificationMessage)
529 this.needToCreateSessionOpenNotificationMessage = false;
530 Fx.Assert(result is CompletedAsyncResult, "result must be CompletedAsyncResult");
531 CompletedAsyncResult.End(result);
532 requestContext = this.GetSessionOpenNotificationRequestContext();
537 valid = this.receiver.EndTryReceive(result, out requestContext);
542 this.HandleReceiveComplete(requestContext);
548 void EnsureChannelAndEndpoint(RequestContext request)
550 this.requestInfo.Channel = this.channel;
552 if (this.requestInfo.Channel == null)
557 this.requestInfo.Channel = this.GetSessionChannel(request.RequestMessage, out this.requestInfo.Endpoint, out addressMatched);
561 this.requestInfo.Channel = this.GetDatagramChannel(request.RequestMessage, out this.requestInfo.Endpoint, out addressMatched);
564 if (this.requestInfo.Channel == null)
566 this.host.RaiseUnknownMessageReceived(request.RequestMessage);
569 this.ReplyContractFilterDidNotMatch(request);
573 this.ReplyAddressFilterDidNotMatch(request);
579 this.requestInfo.Endpoint = this.requestInfo.Channel.EndpointDispatcher;
581 //For sessionful contracts, the InstanceContext throttle is not copied over to the channel
582 //as we create the channel before acquiring the lock
583 if (this.InstanceContextServiceThrottle != null && this.requestInfo.Channel.InstanceContextServiceThrottle == null)
585 this.requestInfo.Channel.InstanceContextServiceThrottle = this.InstanceContextServiceThrottle;
589 this.requestInfo.EndpointLookupDone = true;
591 if (this.requestInfo.Channel == null)
593 // SFx drops a message here
594 TraceUtility.TraceDroppedMessage(request.RequestMessage, this.requestInfo.Endpoint);
599 if (this.requestInfo.Channel.HasSession || this.isCallback)
601 this.requestInfo.DispatchRuntime = this.requestInfo.Channel.DispatchRuntime;
605 this.requestInfo.DispatchRuntime = this.requestInfo.Endpoint.DispatchRuntime;
611 if (null == this.sharedTransactedBatchContext || this.isMainTransactedBatchHandler)
613 if (TryAcquirePump())
615 if (this.receiveSynchronously)
617 ActionItem.Schedule(ChannelHandler.onStartSyncMessagePump, this);
621 if (Thread.CurrentThread.IsThreadPoolThread)
623 IAsyncResult result = this.BeginTryReceive();
624 if ((result != null) && result.CompletedSynchronously)
626 ActionItem.Schedule(ChannelHandler.onContinueAsyncReceive, result);
631 // Since this is not a threadpool thread, we don't know if this thread will exit
632 // while the IO is still pending (which would cancel the IO), so we have to get
633 // over to a threadpool thread which we know will not exit while there is pending IO.
634 ActionItem.Schedule(ChannelHandler.onStartAsyncMessagePump, this);
641 ActionItem.Schedule(ChannelHandler.onStartSingleTransactedBatch, this);
645 ServiceChannel GetDatagramChannel(Message message, out EndpointDispatcher endpoint, out bool addressMatched)
647 addressMatched = false;
648 endpoint = this.GetEndpointDispatcher(message, out addressMatched);
650 if (endpoint == null)
655 if (endpoint.DatagramChannel == null)
657 lock (this.listener.ThisLock)
659 if (endpoint.DatagramChannel == null)
661 endpoint.DatagramChannel = new ServiceChannel(this.binder, endpoint, this.listener.ChannelDispatcher, this.idleManager);
662 this.InitializeServiceChannel(endpoint.DatagramChannel);
667 return endpoint.DatagramChannel;
670 EndpointDispatcher GetEndpointDispatcher(Message message, out bool addressMatched)
672 return this.listener.Endpoints.Lookup(message, out addressMatched);
675 ServiceChannel GetSessionChannel(Message message, out EndpointDispatcher endpoint, out bool addressMatched)
677 addressMatched = false;
679 if (this.channel == null)
683 if (this.channel == null)
685 endpoint = this.GetEndpointDispatcher(message, out addressMatched);
686 if (endpoint != null)
688 this.channel = new ServiceChannel(this.binder, endpoint, this.listener.ChannelDispatcher, this.idleManager);
689 this.InitializeServiceChannel(this.channel);
695 if (this.channel == null)
701 endpoint = this.channel.EndpointDispatcher;
706 void InitializeServiceChannel(ServiceChannel channel)
708 if (this.wasChannelThrottled)
710 // TFS#500703, when the idle timeout was hit, the constructor of ServiceChannel will abort itself directly. So
711 // the session throttle will not be released and thus lead to a service unavailablity.
712 // Note that if the channel is already aborted, the next line "channel.ServiceThrottle = this.throttle;" will throw an exception,
713 // so we are not going to do any more work inside this method.
714 // Ideally we should do a thorough refactoring work for this throttling issue. However, it's too risky as a QFE. We should consider
715 // this in a whole release.
716 // Note that the "wasChannelThrottled" boolean will only be true if we aquired the session throttle. So we don't have to check HasSession
718 if (channel.Aborted && this.throttle != null)
720 // This line will release the "session" throttle.
721 this.throttle.DeactivateChannel();
724 channel.ServiceThrottle = this.throttle;
727 if (this.InstanceContextServiceThrottle != null)
729 channel.InstanceContextServiceThrottle = this.InstanceContextServiceThrottle;
732 ClientRuntime clientRuntime = channel.ClientRuntime;
733 if (clientRuntime != null)
735 Type contractType = clientRuntime.ContractClientType;
736 Type callbackType = clientRuntime.CallbackClientType;
738 if (contractType != null)
740 channel.Proxy = ServiceChannelFactory.CreateProxy(contractType, callbackType, MessageDirection.Output, channel);
744 if (this.listener != null)
746 this.listener.ChannelDispatcher.InitializeChannel((IClientChannel)channel.Proxy);
749 ((IChannel)channel).Open();
752 void ProvideFault(Exception e, ref ErrorHandlerFaultInfo faultInfo)
754 if (this.listener != null)
756 this.listener.ChannelDispatcher.ProvideFault(e, this.requestInfo.Channel == null ? this.binder.Channel.GetProperty<FaultConverter>() : this.requestInfo.Channel.GetProperty<FaultConverter>(), ref faultInfo);
758 else if (this.channel != null)
760 DispatchRuntime dispatchBehavior = this.channel.ClientRuntime.CallbackDispatchRuntime;
761 dispatchBehavior.ChannelDispatcher.ProvideFault(e, this.channel.GetProperty<FaultConverter>(), ref faultInfo);
765 internal bool HandleError(Exception e)
767 ErrorHandlerFaultInfo dummy = new ErrorHandlerFaultInfo();
768 return this.HandleError(e, ref dummy);
771 bool HandleError(Exception e, ref ErrorHandlerFaultInfo faultInfo)
775 Fx.Assert(SR.GetString(SR.GetString(SR.SFxNonExceptionThrown)));
776 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.GetString(SR.SFxNonExceptionThrown))));
778 if (this.listener != null)
780 return listener.ChannelDispatcher.HandleError(e, ref faultInfo);
782 else if (this.channel != null)
784 return this.channel.ClientRuntime.CallbackDispatchRuntime.ChannelDispatcher.HandleError(e, ref faultInfo);
792 bool HandleError(Exception e, RequestContext request, ServiceChannel channel)
794 ErrorHandlerFaultInfo faultInfo = new ErrorHandlerFaultInfo(this.messageVersion.Addressing.DefaultFaultAction);
795 bool replied, replySentAsync;
796 ProvideFaultAndReplyFailure(request, e, ref faultInfo, out replied, out replySentAsync);
800 return this.HandleErrorContinuation(e, request, channel, ref faultInfo, replied);
808 bool HandleErrorContinuation(Exception e, RequestContext request, ServiceChannel channel, ref ErrorHandlerFaultInfo faultInfo, bool replied)
822 this.HandleError(e1);
829 if (!this.HandleError(e, ref faultInfo) && this.hasSession)
835 TimeoutHelper timeoutHelper = new TimeoutHelper(CloseAfterFaultTimeout);
838 channel.Close(timeoutHelper.RemainingTime());
846 this.HandleError(e2);
850 this.binder.CloseAfterFault(timeoutHelper.RemainingTime());
858 this.HandleError(e3);
873 this.binder.CloseAfterFault(CloseAfterFaultTimeout);
881 this.HandleError(e4);
894 void HandleReceiveComplete(RequestContext context)
898 if (this.channel != null)
900 this.channel.HandleReceiveComplete(context);
904 if (context == null && this.hasSession)
909 close = !this.doneReceiving;
910 this.doneReceiving = true;
915 this.receiver.Close();
917 if (this.idleManager != null)
919 this.idleManager.CancelTimer();
922 ServiceThrottle throttle = this.throttle;
923 if (throttle != null)
925 throttle.DeactivateChannel();
933 if ((context == null) && this.incrementedActivityCountInConstructor)
935 this.listener.ChannelDispatcher.Channels.DecrementActivityCount();
940 bool HandleRequest(RequestContext request, OperationContext currentOperationContext)
944 // channel EOF, stop receiving
948 ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? TraceUtility.ExtractActivity(request) : null;
950 using (ServiceModelActivity.BoundOperation(activity))
952 if (this.HandleRequestAsReply(request))
958 if (this.isChannelTerminated)
961 this.ReplyChannelTerminated(request);
965 if (this.requestInfo.RequestContext != null)
967 Fx.Assert("ChannelHandler.HandleRequest: this.requestInfo.RequestContext != null");
970 this.requestInfo.RequestContext = request;
972 if (!this.TryAcquireCallThrottle(request))
974 // this.ThrottleAcquiredForCall will be called to continue
978 // NOTE: from here on down, ensure that this code is the same as ThrottleAcquiredForCall (see 55460)
979 if (this.requestInfo.ChannelHandlerOwnsCallThrottle)
981 Fx.Assert("ChannelHandler.HandleRequest: this.requestInfo.ChannelHandlerOwnsCallThrottle");
983 this.requestInfo.ChannelHandlerOwnsCallThrottle = true;
985 if (!this.TryRetrievingInstanceContext(request))
987 //Would have replied and close the request.
991 this.requestInfo.Channel.CompletedIOOperation();
993 //Only acquire InstanceContext throttle if one doesnt already exist.
994 if (!this.TryAcquireThrottle(request, (this.requestInfo.ExistingInstanceContext == null)))
996 // this.ThrottleAcquired will be called to continue
999 if (this.requestInfo.ChannelHandlerOwnsInstanceContextThrottle)
1001 Fx.Assert("ChannelHandler.HandleRequest: this.requestInfo.ChannelHandlerOwnsInstanceContextThrottle");
1003 this.requestInfo.ChannelHandlerOwnsInstanceContextThrottle = (this.requestInfo.ExistingInstanceContext == null);
1005 if (!this.DispatchAndReleasePump(request, true, currentOperationContext))
1007 // this.DispatchDone will be called to continue
1014 bool HandleRequestAsReply(RequestContext request)
1016 if (this.duplexBinder != null)
1018 if (this.duplexBinder.HandleRequestAsReply(request.RequestMessage))
1026 static void OnStartAsyncMessagePump(object state)
1028 ((ChannelHandler)state).AsyncMessagePump();
1031 static void OnStartSyncMessagePump(object state)
1033 ChannelHandler handler = state as ChannelHandler;
1035 if (TD.ChannelReceiveStopIsEnabled())
1037 TD.ChannelReceiveStop(handler.EventTraceActivity, state.GetHashCode());
1040 if (handler.receiveWithTransaction)
1042 handler.SyncTransactionalMessagePump();
1046 handler.SyncMessagePump();
1050 static void OnStartSingleTransactedBatch(object state)
1052 ChannelHandler handler = state as ChannelHandler;
1053 handler.TransactedBatchLoop();
1056 static void OnAsyncReceiveComplete(IAsyncResult result)
1058 if (!result.CompletedSynchronously)
1060 ((ChannelHandler)result.AsyncState).AsyncMessagePump(result);
1064 static void OnContinueAsyncReceive(object state)
1066 IAsyncResult result = (IAsyncResult)state;
1067 ((ChannelHandler)result.AsyncState).AsyncMessagePump(result);
1070 static void OpenAndEnsurePump(object state)
1072 ((ChannelHandler)state).OpenAndEnsurePump();
1075 void OpenAndEnsurePump()
1077 Exception exception = null;
1080 this.binder.Channel.Open();
1091 if (exception != null)
1093 if (DiagnosticUtility.ShouldTraceWarning)
1095 TraceUtility.TraceEvent(System.Diagnostics.TraceEventType.Warning,
1096 TraceCode.FailedToOpenIncomingChannel,
1097 SR.GetString(SR.TraceCodeFailedToOpenIncomingChannel));
1099 SessionIdleManager idleManager = this.idleManager;
1100 if (idleManager != null)
1102 idleManager.CancelTimer();
1104 if ((this.throttle != null) && this.hasSession)
1106 this.throttle.DeactivateChannel();
1109 bool errorHandled = this.HandleError(exception);
1111 if (this.incrementedActivityCountInConstructor)
1113 this.listener.ChannelDispatcher.Channels.DecrementActivityCount();
1118 this.binder.Channel.Abort();
1127 bool TryReceive(TimeSpan timeout, out RequestContext requestContext)
1129 this.shouldRejectMessageWithOnOpenActionHeader = !this.needToCreateSessionOpenNotificationMessage;
1132 if (this.needToCreateSessionOpenNotificationMessage)
1134 this.needToCreateSessionOpenNotificationMessage = false;
1135 requestContext = this.GetSessionOpenNotificationRequestContext();
1140 valid = this.receiver.TryReceive(timeout, out requestContext);
1145 this.HandleReceiveComplete(requestContext);
1151 void ReplyAddressFilterDidNotMatch(RequestContext request)
1153 FaultCode code = FaultCode.CreateSenderFaultCode(AddressingStrings.DestinationUnreachable,
1154 this.messageVersion.Addressing.Namespace);
1155 string reason = SR.GetString(SR.SFxNoEndpointMatchingAddress, request.RequestMessage.Headers.To);
1157 ReplyFailure(request, code, reason);
1160 void ReplyContractFilterDidNotMatch(RequestContext request)
1162 // By default, the contract filter is just a filter over the set of initiating actions in
1163 // the contract, so we do error messages accordingly
1164 AddressingVersion addressingVersion = this.messageVersion.Addressing;
1165 if (addressingVersion != AddressingVersion.None && request.RequestMessage.Headers.Action == null)
1167 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1168 new MessageHeaderException(
1169 SR.GetString(SR.SFxMissingActionHeader, addressingVersion.Namespace), AddressingStrings.Action, addressingVersion.Namespace));
1173 // some of this code is duplicated in DispatchRuntime.UnhandledActionInvoker
1174 // ideally both places would use FaultConverter and ActionNotSupportedException
1175 FaultCode code = FaultCode.CreateSenderFaultCode(AddressingStrings.ActionNotSupported,
1176 this.messageVersion.Addressing.Namespace);
1177 string reason = SR.GetString(SR.SFxNoEndpointMatchingContract, request.RequestMessage.Headers.Action);
1178 ReplyFailure(request, code, reason, this.messageVersion.Addressing.FaultAction);
1182 void ReplyChannelTerminated(RequestContext request)
1184 FaultCode code = FaultCode.CreateSenderFaultCode(FaultCodeConstants.Codes.SessionTerminated,
1185 FaultCodeConstants.Namespaces.NetDispatch);
1186 string reason = SR.GetString(SR.SFxChannelTerminated0);
1187 string action = FaultCodeConstants.Actions.NetDispatcher;
1188 Message fault = Message.CreateMessage(this.messageVersion, code, reason, action);
1189 ReplyFailure(request, fault, action, reason, code);
1192 void ReplyFailure(RequestContext request, FaultCode code, string reason)
1194 string action = this.messageVersion.Addressing.DefaultFaultAction;
1195 ReplyFailure(request, code, reason, action);
1198 void ReplyFailure(RequestContext request, FaultCode code, string reason, string action)
1200 Message fault = Message.CreateMessage(this.messageVersion, code, reason, action);
1201 ReplyFailure(request, fault, action, reason, code);
1204 void ReplyFailure(RequestContext request, Message fault, string action, string reason, FaultCode code)
1206 FaultException exception = new FaultException(reason, code);
1207 ErrorBehavior.ThrowAndCatch(exception);
1208 ErrorHandlerFaultInfo faultInfo = new ErrorHandlerFaultInfo(action);
1209 faultInfo.Fault = fault;
1210 bool replied, replySentAsync;
1211 ProvideFaultAndReplyFailure(request, exception, ref faultInfo, out replied, out replySentAsync);
1212 this.HandleError(exception, ref faultInfo);
1215 void ProvideFaultAndReplyFailure(RequestContext request, Exception exception, ref ErrorHandlerFaultInfo faultInfo, out bool replied, out bool replySentAsync)
1218 replySentAsync = false;
1219 bool requestMessageIsFault = false;
1222 requestMessageIsFault = request.RequestMessage.IsFault;
1224 #pragma warning suppress 56500 // covered by FxCOP
1234 bool enableFaults = false;
1235 if (this.listener != null)
1237 enableFaults = this.listener.ChannelDispatcher.EnableFaults;
1239 else if (this.channel != null && this.channel.IsClient)
1241 enableFaults = this.channel.ClientRuntime.EnableFaults;
1244 if ((!requestMessageIsFault) && enableFaults)
1246 this.ProvideFault(exception, ref faultInfo);
1247 if (faultInfo.Fault != null)
1249 Message reply = faultInfo.Fault;
1254 if (this.PrepareReply(request, reply))
1256 if (this.sendAsynchronously)
1258 var state = new ContinuationState { ChannelHandler = this, Channel = channel, Exception = exception, FaultInfo = faultInfo, Request = request, Reply = reply };
1259 var result = request.BeginReply(reply, ChannelHandler.onAsyncReplyComplete, state);
1260 if (result.CompletedSynchronously)
1262 ChannelHandler.AsyncReplyComplete(result, state);
1267 replySentAsync = true;
1272 request.Reply(reply);
1279 if (!replySentAsync)
1285 #pragma warning suppress 56500 // covered by FxCOP
1292 this.HandleError(e);
1299 /// Prepares a reply that can either be sent asynchronously or synchronously depending on the value of
1300 /// sendAsynchronously
1302 /// <param name="request">The request context to prepare</param>
1303 /// <param name="reply">The reply to prepare</param>
1304 /// <returns>True if channel is open and prepared reply should be sent; otherwise false.</returns>
1305 bool PrepareReply(RequestContext request, Message reply)
1307 // Ensure we only reply once (we may hit the same error multiple times)
1308 if (this.replied == request)
1312 this.replied = request;
1314 bool canSendReply = true;
1316 Message requestMessage = null;
1319 requestMessage = request.RequestMessage;
1321 #pragma warning suppress 56500 // covered by FxCOP
1330 if (!object.ReferenceEquals(requestMessage, null))
1332 UniqueId requestID = null;
1335 requestID = requestMessage.Headers.MessageId;
1337 catch (MessageHeaderException)
1339 // ---- it - we don't need to correlate the reply if the MessageId header is bad
1341 if (!object.ReferenceEquals(requestID, null) && !this.isManualAddressing)
1343 System.ServiceModel.Channels.RequestReplyCorrelator.PrepareReply(reply, requestID);
1345 if (!this.hasSession && !this.isManualAddressing)
1349 canSendReply = System.ServiceModel.Channels.RequestReplyCorrelator.AddressReply(reply, requestMessage);
1351 catch (MessageHeaderException)
1353 // ---- it - we don't need to address the reply if the FaultTo header is bad
1358 // ObjectDisposeException can happen
1359 // if the channel is closed in a different
1360 // thread. 99% this check will avoid false
1362 return this.IsOpen && canSendReply;
1365 static void AsyncReplyComplete(IAsyncResult result, ContinuationState state)
1369 state.Request.EndReply(result);
1373 DiagnosticUtility.TraceHandledException(e, System.Diagnostics.TraceEventType.Error);
1380 state.ChannelHandler.HandleError(e);
1385 state.Reply.Close();
1389 DiagnosticUtility.TraceHandledException(e, System.Diagnostics.TraceEventType.Error);
1396 state.ChannelHandler.HandleError(e);
1401 state.ChannelHandler.HandleErrorContinuation(state.Exception, state.Request, state.Channel, ref state.FaultInfo, true);
1405 DiagnosticUtility.TraceHandledException(e, System.Diagnostics.TraceEventType.Error);
1412 state.ChannelHandler.HandleError(e);
1415 state.ChannelHandler.EnsurePump();
1418 static void OnAsyncReplyComplete(IAsyncResult result)
1420 if (result.CompletedSynchronously)
1427 var state = (ContinuationState)result.AsyncState;
1428 ChannelHandler.AsyncReplyComplete(result, state);
1432 DiagnosticUtility.TraceHandledException(e, System.Diagnostics.TraceEventType.Error);
1443 if (this.isConcurrent)
1445 Interlocked.Exchange(ref this.isPumpAcquired, 0);
1449 void SyncMessagePump()
1451 OperationContext existingOperationContext = OperationContext.Current;
1454 OperationContext currentOperationContext = new OperationContext(this.host);
1455 OperationContext.Current = currentOperationContext;
1459 RequestContext request;
1461 this.requestInfo.Cleanup();
1463 while (!TryReceive(TimeSpan.MaxValue, out request))
1467 if (!HandleRequest(request, currentOperationContext))
1472 if (!TryAcquirePump())
1477 currentOperationContext.Recycle();
1482 OperationContext.Current = existingOperationContext;
1486 [MethodImpl(MethodImplOptions.NoInlining)]
1487 void SyncTransactionalMessagePump()
1491 bool completedSynchronously;
1492 if (null == sharedTransactedBatchContext)
1494 completedSynchronously = TransactedLoop();
1498 completedSynchronously = TransactedBatchLoop();
1501 if (!completedSynchronously)
1508 bool TransactedLoop()
1512 this.receiver.WaitForMessage();
1514 catch (Exception ex)
1521 if (!this.HandleError(ex))
1527 RequestContext request;
1528 Transaction tx = CreateOrGetAttachedTransaction();
1529 OperationContext existingOperationContext = OperationContext.Current;
1533 OperationContext currentOperationContext = new OperationContext(this.host);
1534 OperationContext.Current = currentOperationContext;
1538 this.requestInfo.Cleanup();
1540 bool received = TryTransactionalReceive(tx, out request);
1547 if (null == request)
1552 TransactionMessageProperty.Set(tx, request.RequestMessage);
1554 if (!HandleRequest(request, currentOperationContext))
1559 if (!TryAcquirePump())
1564 tx = CreateOrGetAttachedTransaction();
1565 currentOperationContext.Recycle();
1570 OperationContext.Current = existingOperationContext;
1574 bool TransactedBatchLoop()
1576 if (null != this.transactedBatchContext)
1578 if (this.transactedBatchContext.InDispatch)
1580 this.transactedBatchContext.ForceRollback();
1581 this.transactedBatchContext.InDispatch = false;
1583 if (!this.transactedBatchContext.IsActive)
1585 if (!this.isMainTransactedBatchHandler)
1589 this.transactedBatchContext = null;
1593 if (null == this.transactedBatchContext)
1597 this.receiver.WaitForMessage();
1599 catch (Exception ex)
1606 if (!this.HandleError(ex))
1611 this.transactedBatchContext = this.sharedTransactedBatchContext.CreateTransactedBatchContext();
1614 OperationContext existingOperationContext = OperationContext.Current;
1618 OperationContext currentOperationContext = new OperationContext(this.host);
1619 OperationContext.Current = currentOperationContext;
1621 RequestContext request;
1623 while (this.transactedBatchContext.IsActive)
1625 this.requestInfo.Cleanup();
1627 bool valid = TryTransactionalReceive(this.transactedBatchContext.Transaction, out request);
1633 this.transactedBatchContext.ForceCommit();
1638 this.transactedBatchContext.ForceRollback();
1643 if (null == request)
1645 this.transactedBatchContext.ForceRollback();
1649 TransactionMessageProperty.Set(this.transactedBatchContext.Transaction, request.RequestMessage);
1651 this.transactedBatchContext.InDispatch = true;
1652 if (!HandleRequest(request, currentOperationContext))
1657 if (this.transactedBatchContext.InDispatch)
1659 this.transactedBatchContext.ForceRollback();
1660 this.transactedBatchContext.InDispatch = false;
1664 if (!TryAcquirePump())
1666 Fx.Assert("System.ServiceModel.Dispatcher.ChannelHandler.TransactedBatchLoop(): (TryAcquiredPump returned false)");
1670 currentOperationContext.Recycle();
1675 OperationContext.Current = existingOperationContext;
1680 Transaction CreateOrGetAttachedTransaction()
1682 if (null != this.acceptTransaction)
1686 if (null != this.acceptTransaction)
1688 Transaction tx = this.acceptTransaction.Transaction;
1689 this.acceptTransaction = null;
1695 if (null != this.InstanceContext && this.InstanceContext.HasTransaction)
1697 return InstanceContext.Transaction.Attached;
1701 return TransactionBehavior.CreateTransaction(
1702 this.listener.ChannelDispatcher.TransactionIsolationLevel,
1703 TransactionBehavior.NormalizeTimeout(this.listener.ChannelDispatcher.TransactionTimeout));
1707 // calls receive on the channel; returns false if no message during the "short timeout"
1708 bool TryTransactionalReceive(Transaction tx, out RequestContext request)
1711 bool received = false;
1715 using (TransactionScope scope = new TransactionScope(tx))
1717 if (null != this.sharedTransactedBatchContext)
1719 lock (this.sharedTransactedBatchContext.ReceiveLock)
1721 if (this.transactedBatchContext.AboutToExpire)
1726 received = this.receiver.TryReceive(TimeSpan.Zero, out request);
1731 TimeSpan receiveTimeout = TimeoutHelper.Min(this.listener.ChannelDispatcher.TransactionTimeout, this.listener.ChannelDispatcher.DefaultCommunicationTimeouts.ReceiveTimeout);
1732 received = this.receiver.TryReceive(TransactionBehavior.NormalizeTimeout(receiveTimeout), out request);
1739 this.HandleReceiveComplete(request);
1742 catch (ObjectDisposedException ex) // thrown from the transaction
1744 this.HandleError(ex);
1748 catch (TransactionException ex)
1750 this.HandleError(ex);
1754 catch (Exception ex)
1761 if (!this.HandleError(ex))
1770 // This callback always occurs async and always on a dirty thread
1771 internal void ThrottleAcquiredForCall()
1773 RequestContext request = this.requestWaitingForThrottle;
1774 this.requestWaitingForThrottle = null;
1775 if (this.requestInfo.ChannelHandlerOwnsCallThrottle)
1777 Fx.Assert("ChannelHandler.ThrottleAcquiredForCall: this.requestInfo.ChannelHandlerOwnsCallThrottle");
1779 this.requestInfo.ChannelHandlerOwnsCallThrottle = true;
1781 if (!this.TryRetrievingInstanceContext(request))
1783 //Should reply/close request and also close the pump
1788 this.requestInfo.Channel.CompletedIOOperation();
1790 if (this.TryAcquireThrottle(request, (this.requestInfo.ExistingInstanceContext == null)))
1792 if (this.requestInfo.ChannelHandlerOwnsInstanceContextThrottle)
1794 Fx.Assert("ChannelHandler.ThrottleAcquiredForCall: this.requestInfo.ChannelHandlerOwnsInstanceContextThrottle");
1796 this.requestInfo.ChannelHandlerOwnsInstanceContextThrottle = (this.requestInfo.ExistingInstanceContext == null);
1798 if (this.DispatchAndReleasePump(request, false, null))
1805 bool TryRetrievingInstanceContext(RequestContext request)
1809 return TryRetrievingInstanceContextCore(request);
1811 catch (Exception ex)
1818 DiagnosticUtility.TraceHandledException(ex, TraceEventType.Error);
1838 //Return: False denotes failure, Caller should discard the request.
1839 // : True denotes operation is sucessful.
1840 bool TryRetrievingInstanceContextCore(RequestContext request)
1842 bool releasePump = true;
1845 if (!this.requestInfo.EndpointLookupDone)
1847 this.EnsureChannelAndEndpoint(request);
1850 if (this.requestInfo.Channel == null)
1855 if (this.requestInfo.DispatchRuntime != null)
1857 IContextChannel transparentProxy = this.requestInfo.Channel.Proxy as IContextChannel;
1860 this.requestInfo.ExistingInstanceContext = this.requestInfo.DispatchRuntime.InstanceContextProvider.GetExistingInstanceContext(request.RequestMessage, transparentProxy);
1861 releasePump = false;
1869 this.requestInfo.Channel = null;
1870 this.HandleError(e, request, channel);
1876 // This can happen if we are pumping for an async client,
1877 // and we receive a bogus reply. In that case, there is no
1878 // DispatchRuntime, because we are only expecting replies.
1880 // One possible fix for this would be in DuplexChannelBinder
1881 // to drop all messages with a RelatesTo that do not match a
1884 // However, that would not fix:
1885 // (a) we could get a valid request message with a
1886 // RelatesTo that we should try to process.
1887 // (b) we could get a reply message that does not have
1890 // So we do the null check here.
1892 // SFx drops a message here
1893 TraceUtility.TraceDroppedMessage(request.RequestMessage, this.requestInfo.Endpoint);
1905 this.HandleError(e, request, channel);
1919 // This callback always occurs async and always on a dirty thread
1920 internal void ThrottleAcquired()
1922 RequestContext request = this.requestWaitingForThrottle;
1923 this.requestWaitingForThrottle = null;
1924 if (this.requestInfo.ChannelHandlerOwnsInstanceContextThrottle)
1926 Fx.Assert("ChannelHandler.ThrottleAcquired: this.requestInfo.ChannelHandlerOwnsInstanceContextThrottle");
1928 this.requestInfo.ChannelHandlerOwnsInstanceContextThrottle = (this.requestInfo.ExistingInstanceContext == null);
1930 if (this.DispatchAndReleasePump(request, false, null))
1936 bool TryAcquireThrottle(RequestContext request, bool acquireInstanceContextThrottle)
1938 ServiceThrottle throttle = this.throttle;
1939 if ((throttle != null) && (throttle.IsActive))
1941 this.requestWaitingForThrottle = request;
1943 if (throttle.AcquireInstanceContextAndDynamic(this, acquireInstanceContextThrottle))
1945 this.requestWaitingForThrottle = null;
1959 bool TryAcquireCallThrottle(RequestContext request)
1961 ServiceThrottle throttle = this.throttle;
1962 if ((throttle != null) && (throttle.IsActive))
1964 this.requestWaitingForThrottle = request;
1966 if (throttle.AcquireCall(this))
1968 this.requestWaitingForThrottle = null;
1982 bool TryAcquirePump()
1984 if (this.isConcurrent)
1986 return Interlocked.CompareExchange(ref this.isPumpAcquired, 1, 0) == 0;
1994 public EndpointDispatcher Endpoint;
1995 public InstanceContext ExistingInstanceContext;
1996 public ServiceChannel Channel;
1997 public bool EndpointLookupDone;
1998 public DispatchRuntime DispatchRuntime;
1999 public RequestContext RequestContext;
2000 public ChannelHandler ChannelHandler;
2001 public bool ChannelHandlerOwnsCallThrottle; // if true, we are responsible for call throttle
2002 public bool ChannelHandlerOwnsInstanceContextThrottle; // if true, we are responsible for instance/dynamic throttle
2004 public RequestInfo(ChannelHandler channelHandler)
2006 this.Endpoint = null;
2007 this.ExistingInstanceContext = null;
2008 this.Channel = null;
2009 this.EndpointLookupDone = false;
2010 this.DispatchRuntime = null;
2011 this.RequestContext = null;
2012 this.ChannelHandler = channelHandler;
2013 this.ChannelHandlerOwnsCallThrottle = false;
2014 this.ChannelHandlerOwnsInstanceContextThrottle = false;
2017 public void Cleanup()
2019 if (this.ChannelHandlerOwnsInstanceContextThrottle)
2021 this.ChannelHandler.throttle.DeactivateInstanceContext();
2022 this.ChannelHandlerOwnsInstanceContextThrottle = false;
2025 this.Endpoint = null;
2026 this.ExistingInstanceContext = null;
2027 this.Channel = null;
2028 this.EndpointLookupDone = false;
2029 this.RequestContext = null;
2030 if (this.ChannelHandlerOwnsCallThrottle)
2032 this.ChannelHandler.DispatchDone();
2033 this.ChannelHandlerOwnsCallThrottle = false;
2038 EventTraceActivity TraceDispatchMessageStart(Message message)
2040 if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled && message != null)
2042 EventTraceActivity eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message);
2043 if (TD.DispatchMessageStartIsEnabled())
2045 TD.DispatchMessageStart(eventTraceActivity);
2047 return eventTraceActivity;
2054 /// Data structure used to carry state for asynchronous replies
2056 struct ContinuationState
2058 public ChannelHandler ChannelHandler;
2059 public Exception Exception;
2060 public RequestContext Request;
2061 public Message Reply;
2062 public ServiceChannel Channel;
2063 public ErrorHandlerFaultInfo FaultInfo;