private async Task WriteMessageAsyncInternal(Message message, Stream stream) { await TaskHelpers.EnsureDefaultTaskScheduler(); await WriteMessageAsync(message, stream); }
private async Task <int> ReadAsyncInternal(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { await TaskHelpers.EnsureDefaultTaskScheduler(); return(await ReadAsync(buffer, offset, count, cancellationToken)); }
private async Task WriteAsyncInternal(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { await TaskHelpers.EnsureDefaultTaskScheduler(); await WriteAsync(buffer, offset, count, cancellationToken); }
internal async Task <MessageRpc> ProcessMessageAsync(MessageRpc rpc) { if (rpc.Operation.IsOneWay) { await rpc.RequestContext.ReplyAsync(null); rpc.OperationContext.RequestContext = null; } else { if (!rpc.Channel.IsReplyChannel && ((object)rpc.RequestID == null) && (rpc.Operation.Action != MessageHeaders.WildcardAction)) { CommunicationException error = new CommunicationException(SR.SFxOneWayMessageToTwoWayMethod0); throw TraceUtility.ThrowHelperError(error, rpc.Request); } if (!manualAddressing) { EndpointAddress replyTo = rpc.ReplyToInfo.ReplyTo; if (replyTo != null && replyTo.IsNone && rpc.Channel.IsReplyChannel) { CommunicationException error = new CommunicationException(SR.SFxRequestReplyNone); throw TraceUtility.ThrowHelperError(error, rpc.Request); } if (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.Format(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.Format(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.Format(SR.SFxRequestHasInvalidFromOnServer, from.Uri, remoteUri); Exception error = new InvalidOperationException(text); throw TraceUtility.ThrowHelperError(error, rpc.Request); } } } } } } if (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); //} instance.EnsureInstanceContext(ref rpc); // TODO: Work out what function the pending list has and re-add/replace/remove functionality //TransferChannelFromPendingList(ref rpc); AcquireDynamicInstanceContext(ref rpc); AfterReceiveRequest(ref rpc); //if (!this.ignoreTransactionFlow) //{ // // Transactions need to have the context in the message // rpc.TransactionMessageProperty = TransactionMessageProperty.TryGet(rpc.Request); //} rpc = await concurrency.LockInstanceAsync(rpc); 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); // } //} //rpc.NextProcessor = 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); // } // } //} //rpc.NextProcessor = processMessage41; try { // TaskHelpers has an extension method which enables awaitting a sync context to run continuation on it. await thread.GetSyncContext(rpc); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(e.Message, e); } // 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. // TODO: This is the concurrency gate. If the service is concurrent, this allows another receive to happen. This mechanism needs replacing. //if (concurrency.IsConcurrent(ref rpc)) //{ // rpc.EnsureReceive(); //} instance.EnsureServiceInstance(ref rpc); try { //if (!rpc.Operation.IsSynchronous) //{ // // If async call completes in sync, it tells us through the gate below // rpc.PrepareInvokeContinueGate(); //} //if (this.transaction != null) //{ // this.transaction.InitializeCallContext(ref rpc); //} //SetActivityIdOnThread(ref rpc); rpc = await rpc.Operation.InvokeAsync(rpc); } catch { // This catch clause forces ClearCallContext to run prior to stackwalks exiting this frame. throw; } try { // Switch back to thread pool if we're using a non-default Sync Context await TaskHelpers.EnsureDefaultTaskScheduler(); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(e.Message, e); } try { error.ProvideMessageFault(ref rpc); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } error.HandleError(e); } PrepareReply(ref rpc); if (rpc.CanSendReply) { rpc.ReplyTimeoutHelper = new TimeoutHelper(rpc.Channel.OperationTimeout); } if (rpc.CanSendReply) { //if (rpc.Reply != null) //{ // TraceUtility.MessageFlowAtMessageSent(rpc.Reply, rpc.EventTraceActivity); //} rpc = await ReplyAsync(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. // Fx.Assert( !object.ReferenceEquals(rpc.ErrorProcessor, processMessageCleanupError), "ProcessMessageCleanup run twice on the same MessageRpc!"); rpc.ErrorProcessor = processMessageCleanupError; bool replyWasSent = false; if (rpc.CanSendReply) { replyWasSent = rpc.SuccessfullySendReply; } try { try { if (rpc.DidDeserializeRequestBody) { rpc.Request.Close(); } } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } error.HandleError(e); } rpc.DisposeParameters(false); //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; } 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; } error.HandleError(e); } } try { rpc.OperationContext.FireOperationCompleted(); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e); } instance.AfterReply(ref rpc, error); if (rpc.SuccessfullyLockedInstance) { try { concurrency.UnlockInstance(ref rpc); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } Fx.Assert("Exceptions should be caught by callee"); rpc.InstanceContext.FaultInternal(); error.HandleError(e); } } if (terminate != null) { try { terminate.AfterReply(ref rpc); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } error.HandleError(e); } } if (rpc.SuccessfullyIncrementedActivity) { try { rpc.Channel.DecrementActivity(); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } error.HandleError(e); } } } finally { //if (rpc.MessageRpcOwnsInstanceContextThrottle && rpc.channelHandler.InstanceContextServiceThrottle != null) //{ // rpc.channelHandler.InstanceContextServiceThrottle.DeactivateInstanceContext(); //} //if (rpc.Activity != null && DiagnosticUtility.ShouldUseActivity) //{ // rpc.Activity.Stop(); //} } error.HandleError(ref rpc); return(rpc); }
private async Task <Message> RequestAsyncInternal(Message message, TimeSpan timeout) { await TaskHelpers.EnsureDefaultTaskScheduler(); return(await RequestAsync(message, timeout)); }
public static async Task OnOpenAsyncInternal(CommunicationObject communicationObject, TimeSpan timeout) { await TaskHelpers.EnsureDefaultTaskScheduler(); await communicationObject.OnOpenAsync(timeout); }
private async Task OpenAsyncInternal(TimeSpan timeout) { await TaskHelpers.EnsureDefaultTaskScheduler(); await((IAsyncCommunicationObject)this).OpenAsync(timeout); }
internal async Task <MessageRpc> ProcessMessageAsync(MessageRpc rpc) { if (rpc.Operation.IsOneWay) { await rpc.RequestContext.ReplyAsync(null); rpc.OperationContext.RequestContext = null; } else { if (!rpc.Channel.IsReplyChannel && ((object)rpc.RequestID == null) && (rpc.Operation.Action != MessageHeaders.WildcardAction)) { CommunicationException error = new CommunicationException(SR.SFxOneWayMessageToTwoWayMethod0); throw TraceUtility.ThrowHelperError(error, rpc.Request); } if (!_manualAddressing) { EndpointAddress replyTo = rpc.ReplyToInfo.ReplyTo; if (replyTo != null && replyTo.IsNone && rpc.Channel.IsReplyChannel) { CommunicationException error = new CommunicationException(SR.SFxRequestReplyNone); throw TraceUtility.ThrowHelperError(error, rpc.Request); } if (_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.Format(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.Format(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.Format(SR.SFxRequestHasInvalidFromOnServer, from.Uri, remoteUri); Exception error = new InvalidOperationException(text); throw TraceUtility.ThrowHelperError(error, rpc.Request); } } } } } } if (_concurrency.IsConcurrent(rpc)) { rpc.Channel.IncrementActivity(); rpc.SuccessfullyIncrementedActivity = true; } // TODO: Make authenticationBehavior Async if (_authenticationBehavior != null) { _authenticationBehavior.Authenticate(ref rpc); } // TODO: Make authorizationBehavior Async if (_authorizationBehavior != null) { _authorizationBehavior.Authorize(ref rpc); } await InstanceBehavior.EnsureInstanceContextAsync(rpc); TransferChannelFromPendingList(rpc); await AcquireDynamicInstanceContextAsync(rpc); AfterReceiveRequest(ref rpc); await _concurrency.LockInstanceAsync(rpc); rpc.SuccessfullyLockedInstance = true; try { // TaskHelpers has an extension method which enables awaitting a sync context to run continuation on it. await _thread.GetSyncContext(rpc); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(e.Message, e); } // 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 based on the assumption // that running on UI thread should guarantee in-order delivery if // the SynchronizationContext is single threaded. if (_concurrency.IsConcurrent(rpc)) { rpc.EnsureReceive(); if (!rpc._processCallReturned) { // To allow transport receive loop to get next request, the call to dispatch the current message needs to return. // If all previous await's have completed synchronously, execution needs to be forced to continue on another thread. // This code causes this method to continue on another thread and any calling receive pump (such as NetTcp) will // use this thread to request the next message. It might be better to switch that so this thread continues on this // thread and the caller has to run on a new thread. await Task.Yield(); } } InstanceBehavior.EnsureServiceInstance(rpc); try { SetActivityIdOnThread(rpc); rpc = await rpc.Operation.InvokeAsync(rpc); } catch { // This catch clause forces ClearCallContext to run prior to stackwalks exiting this frame. throw; } try { // Switch back to thread pool if we're using a non-default Sync Context. This only switches threads if needed. await TaskHelpers.EnsureDefaultTaskScheduler(); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(e.Message, e); } await ProcessError(rpc); if (!_concurrency.IsConcurrent(rpc)) { rpc.EnsureReceive(); } return(rpc); }