public ProcessRequestAsyncResult(RoutingService service, Message message, AsyncCallback callback, object state)
            : base(callback, state)
        {
            this.allCompletedSync = true;
            this.service          = service;
            this.messageRpc       = new MessageRpc(message, OperationContext.Current, service.ChannelExtension.ImpersonationRequired);
            if (TD.RoutingServiceProcessingMessageIsEnabled())
            {
                TD.RoutingServiceProcessingMessage(this.messageRpc.EventTraceActivity, this.messageRpc.UniqueID,
                                                   message.Headers.Action, this.messageRpc.OperationContext.EndpointDispatcher.EndpointAddress.Uri.ToString(), messageRpc.Transaction != null ? "True" : "False");
            }

            try
            {
                EndpointNameMessageFilter.Set(this.messageRpc.Message.Properties, service.ChannelExtension.EndpointName);
                this.messageRpc.RouteToSingleEndpoint <TContract>(this.service.RoutingConfig);
            }
            catch (MultipleFilterMatchesException matchesException)
            {
                // Wrap this exception with one that is more meaningful to users of RoutingService:
                throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR.ReqReplyMulticastNotSupported(this.messageRpc.OperationContext.Channel.LocalAddress), matchesException));
            }

            while (this.StartProcessing())
            {
            }
        }
Пример #2
0
            public CallState(MessageRpc messageRpc)
            {
                this.nullContextScope = new OperationContextScope((OperationContext)null);

                if (messageRpc.windowsIdentity != null)
                {
                    this.impersonation = messageRpc.windowsIdentity.Impersonate();
                }
            }
Пример #3
0
        bool CompleteReceiveContextCompleted(IAsyncResult result)
        {
            MessageRpc messageRpc = this.service.SessionMessages[this.sessionMessageIndex];

            messageRpc.ReceiveContext.EndComplete(result);

            if (++this.sessionMessageIndex >= this.service.SessionMessages.Count)
            {
                return(this.DoneCompletingReceiveContexts());
            }
            return(true);
        }
Пример #4
0
        void ClientOperationComplete(IAsyncResult result)
        {
            MessageRpc    messageRpc  = this.service.SessionMessages[this.sessionMessageIndex];
            SendOperation currentDest = messageRpc.Operations[this.destinationIndex];

            this.client.EndOperation(result);
            currentDest.TransmitSucceeded(this.service.GetTransactionForSending(messageRpc));

            if (TD.RoutingServiceTransmitSucceededIsEnabled())
            {
                TD.RoutingServiceTransmitSucceeded(messageRpc.EventTraceActivity, messageRpc.UniqueID, this.destinationIndex.ToString(TD.Culture), currentDest.CurrentEndpoint.ToString());
            }
            MoveToNextClientOperation(messageRpc.Operations.Count);
        }
Пример #5
0
 internal Transaction GetTransactionForSending(MessageRpc messageRpc)
 {
     if (messageRpc != null && messageRpc.Transaction != null)
     {
         return(messageRpc.Transaction);
     }
     if (this.ReceiveTransaction != null)
     {
         //This is the transaction used for the receive, we cannot perform error handling since we
         //didn't create it.
         return(this.ReceiveTransaction);
     }
     else
     {
         //This could be null, indicating non-transactional behavior
         return(this.RetryTransaction);
     }
 }
Пример #6
0
        bool CompleteCurrentReceiveContext()
        {
            if (this.service.SessionException != null)
            {
                //This means at least one multicast branch did not reach any of the configured endpoints
                this.Fault(this.service.SessionException);
                return(false);
            }

            bool       keepGoing;
            MessageRpc messageRpc = this.service.SessionMessages[this.sessionMessageIndex];

            if (messageRpc.ReceiveContext != null)
            {
                if (TD.RoutingServiceCompletingReceiveContextIsEnabled())
                {
                    TD.RoutingServiceCompletingReceiveContext(messageRpc.EventTraceActivity, messageRpc.UniqueID);
                }

                IAsyncResult result;
                using (this.PrepareTransactionalCall(this.service.GetTransactionForSending(messageRpc)))
                {
                    result = messageRpc.ReceiveContext.BeginComplete(this.timeoutHelper.RemainingTime(),
                                                                     this.PrepareAsyncCompletion(completeReceiveContextCallback), this);
                }
                if (this.CheckSyncContinue(result))
                {
                    keepGoing = this.CompleteReceiveContextCompleted(result);
                }
                else
                {
                    keepGoing = false;
                }
            }
            else
            {
                // Either all messages have RC or all messages don't have RC.  Since we don't have one
                // we know that none of these messages will, so we don't have to look at the other messages
                Fx.Assert("We shouldn't enter CompletingReceiveContexts state if the binding is not ReceiveContext capable");
                keepGoing = this.DoneCompletingReceiveContexts();
            }

            return(keepGoing);
        }
Пример #7
0
        public ProcessMessagesAsyncResult(Message message, RoutingService service, TimeSpan timeout, AsyncCallback callback, object state)
            : base(callback, state)
        {
            this.service          = service;
            this.channelExtension = service.ChannelExtension;
            this.timeoutHelper    = new TimeoutHelper(timeout);
            this.timeoutHelper.RemainingTime(); //Start the timer

            if (message == null)
            {
                //Null message means end of session, time to close everything
                this.closeOutboundChannels = true;
                this.state = ProcessingState.ClosingChannels;
            }
            else
            {
                this.closeOutboundChannels = false;
                MessageRpc messageRpc = new MessageRpc(message, OperationContext.Current, this.channelExtension.ImpersonationRequired);
                if (TD.RoutingServiceProcessingMessageIsEnabled())
                {
                    TD.RoutingServiceProcessingMessage(messageRpc.EventTraceActivity, messageRpc.UniqueID, messageRpc.Message.Headers.Action, messageRpc.OperationContext.EndpointDispatcher.EndpointAddress.Uri.ToString(), (messageRpc.Transaction != null).ToString());
                }

                EndpointNameMessageFilter.Set(messageRpc.Message.Properties, this.channelExtension.EndpointName);
                messageRpc.RouteToEndpoints <TContract>(this.service.RoutingConfig);
                this.service.SessionMessages.Add(messageRpc);

                this.sessionMessageIndex = this.service.SessionMessages.Count - 1;
                if (this.sessionMessageIndex == 0)
                {
                    //First message, do initialization stuff
                    this.state = ProcessingState.Initial;
                }
                else
                {
                    this.state = ProcessingState.SendingSessionMessages;
                }
            }
            this.ProcessWhileSync();
        }
Пример #8
0
        internal void CreateNewTransactionIfNeeded(MessageRpc messageRpc)
        {
            if (messageRpc.Transaction != null && this.ChannelExtension.TransactedReceiveEnabled)
            {
                if (TD.RoutingServiceUsingExistingTransactionIsEnabled())
                {
                    TD.RoutingServiceUsingExistingTransaction(messageRpc.EventTraceActivity, messageRpc.Transaction.TransactionInformation.LocalIdentifier);
                }
                Fx.Assert(this.ReceiveTransaction == null, "Should only happen at the start of a session.");
                this.ReceiveTransaction = messageRpc.Transaction;
                return;
            }
            else if (!this.ChannelExtension.TransactedReceiveEnabled || !this.ChannelExtension.ReceiveContextEnabled)
            {
                return;
            }

            Fx.Assert(this.RetryTransaction == null, "Logic error, we shouldn't be calling CreateNewTransactionIfNeeded if we have a RC Transaction");

            ChannelDispatcher  channelDispatcher = this.operationContext.EndpointDispatcher.ChannelDispatcher;
            TimeSpan           timeout           = channelDispatcher.TransactionTimeout;
            IsolationLevel     isolation         = channelDispatcher.TransactionIsolationLevel;
            TransactionOptions options           = new TransactionOptions();

            if (timeout > TimeSpan.Zero)
            {
                options.Timeout = timeout;
            }
            if (isolation != IsolationLevel.Unspecified)
            {
                options.IsolationLevel = isolation;
            }

            this.RetryTransaction = new CommittableTransaction(options);
            if (TD.RoutingServiceCreatingTransactionIsEnabled())
            {
                TD.RoutingServiceCreatingTransaction(messageRpc.EventTraceActivity, this.RetryTransaction.TransactionInformation.LocalIdentifier);
            }
        }
Пример #9
0
        bool HandleClientOperationFailure(Exception e)
        {
            if (TD.RoutingServiceTransmitFailedIsEnabled())
            {
                TD.RoutingServiceTransmitFailed(null, this.client.Key.ToString(), e);
            }

            if (!(e is CommunicationException || e is TimeoutException))
            {
                //We only move to backup for CommunicationExceptions and TimeoutExceptions
                return(false);
            }

            bool          canHandle;
            MessageRpc    messageRpc    = this.service.SessionMessages[this.sessionMessageIndex];
            SendOperation sendOperation = messageRpc.Operations[this.destinationIndex];

            if ((e is CommunicationObjectAbortedException || e is CommunicationObjectFaultedException) &&
                !this.channelExtension.HasSession)
            {
                // Messages on a non sessionful channel share outbound connections and can
                // fail due to other messages failing on the same channel
                bool canRetry = (this.channelExtension.ReceiveContextEnabled || !this.channelExtension.TransactedReceiveEnabled);
                if (canRetry && !this.abortedRetry)
                {
                    //No session and ReceiveContext or non transactional, retry the message 1 time (before moving to backup)
                    this.abortedRetry = true;
                    this.ResetState();
                    return(true);
                }
            }
            else if (e is EndpointNotFoundException)
            {
                // The channel may not fault for this exception for bindings other than netTcpBinding
                // We abort the channel in that case. We proactively clean up so that we don't have to cleanup later
                SessionChannels sessionChannels = this.service.GetSessionChannels(messageRpc.Impersonating);
                if (sessionChannels != null)
                {
                    sessionChannels.AbortChannel(sendOperation.CurrentEndpoint);
                }
            }
            else if (e is MessageSecurityException)
            {
                // The service may have been stopped and restarted without the routing service knowledge.
                // When we try to use a cached channel to the service, the channel can fault due to this exception
                // The faulted channel gets cleaned up and we retry one more time only when service has backup
                // If there is no backup, we do not retry since we do not create a buffered message to prevent performance degradation
                if (!this.abortedRetry && (sendOperation.AlternateEndpointCount > 0))
                {
                    this.abortedRetry = true;
                    this.ResetState();
                    return(true);
                }
            }

            if (sendOperation.TryMoveToAlternate(e))
            {
                if (TD.RoutingServiceMovedToBackupIsEnabled())
                {
                    TD.RoutingServiceMovedToBackup(messageRpc.EventTraceActivity, messageRpc.UniqueID, this.destinationIndex.ToString(TD.Culture), sendOperation.CurrentEndpoint.ToString());
                }
                this.ResetState();
                canHandle = true;
            }
            else if (this.service.GetTransactionForSending(messageRpc) == null)
            {
                // This is OneWay with no Transaction...
                // store this exception for when we complete, but continue any multicasting
                this.service.SessionException = e;

                // Mark the SendOperation as 'Sent' because there's no more work we can do (non-tx and no more backups)
                sendOperation.TransmitSucceeded(null);

                if (this.channelExtension.HasSession)
                {
                    this.channelExtension.SessionChannels.AbortChannel(this.client.Key);
                }

                this.MoveToNextClientOperation(messageRpc.Operations.Count);
                canHandle = true;
            }
            else
            {
                canHandle = false;
            }

            return(canHandle);
        }
Пример #10
0
        bool SendToCurrentClient()
        {
            MessageRpc    messageRpc    = this.service.SessionMessages[this.sessionMessageIndex];
            SendOperation sendOperation = messageRpc.Operations[this.destinationIndex];

            if (sendOperation.Sent)
            {
                this.MoveToNextClientOperation(messageRpc.Operations.Count);
                return(true);
            }
            else if (!this.channelExtension.ReceiveContextEnabled &&
                     this.channelExtension.TransactedReceiveEnabled &&
                     sendOperation.HasAlternate)
            {
                // We can't do error handling for oneway Transactional unless there's RC.
                throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR.ErrorHandlingNotSupportedTxNoRC(messageRpc.OperationContext.Channel.LocalAddress)));
            }

            RoutingEndpointTrait endpointTrait = sendOperation.CurrentEndpoint;

            this.client = this.service.GetOrCreateClient <TContract>(endpointTrait, messageRpc.Impersonating);
            try
            {
                // We always work on cloned message when there are backup endpoints to handle exception cases
                Message message;
                if (messageRpc.Operations.Count == 1 && sendOperation.AlternateEndpointCount == 0)
                {
                    message = messageRpc.Message;
                }
                else
                {
                    message = messageRpc.CreateBuffer().CreateMessage();
                }

                sendOperation.PrepareMessage(message);
                IAsyncResult result;

                if (TD.RoutingServiceTransmittingMessageIsEnabled())
                {
                    TD.RoutingServiceTransmittingMessage(messageRpc.EventTraceActivity, messageRpc.UniqueID, this.destinationIndex.ToString(TD.Culture), this.client.Key.ToString());
                }

                Transaction transaction = this.service.GetTransactionForSending(messageRpc);
                using (this.PrepareTransactionalCall(transaction))
                {
                    IDisposable impersonationContext = null;
                    try
                    {
                        //Perform the assignment in a finally block so it won't be interrupted asynchronously
                        try { }
                        finally
                        {
                            impersonationContext = messageRpc.PrepareCall();
                        }

                        result = this.client.BeginOperation(message, transaction, this.PrepareAsyncCompletion(clientOperationCallback), this);
                    }
                    finally
                    {
                        if (impersonationContext != null)
                        {
                            impersonationContext.Dispose();
                        }
                    }
                }

                if (this.CheckSyncContinue(result))
                {
                    this.ClientOperationComplete(result);
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            catch (Exception exception)
            {
                if (Fx.IsFatal(exception))
                {
                    throw;
                }

                //See if we can handle this Exception...
                if (this.HandleClientOperationFailure(exception))
                {
                    return(true);
                }
                throw;
            }
        }