ReliableMessagingHelpers.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / ReliableMessagingHelpers.cs / 1 / ReliableMessagingHelpers.cs

                            //---------------------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------------------
namespace System.ServiceModel.Channels
{ 
    using System.Collections.Generic;
    using System.Diagnostics; 
    using System.ServiceModel; 
    using System.ServiceModel.Diagnostics;
    using System.ServiceModel.Dispatcher; 
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.ServiceModel.Security;
    using System.Threading; 
    using System.Xml;
 
    internal delegate void OperationEndCallback(IAsyncResult result); 
    internal delegate IAsyncResult OperationWithTimeoutBeginCallback(TimeSpan timeout, AsyncCallback asyncCallback, object asyncState);
    internal delegate void OperationWithTimeoutCallback(TimeSpan timeout); 

    static class OperationWithTimeoutComposer
    {
        public static IAsyncResult BeginComposeAsyncOperations( 
            TimeSpan timeout, OperationWithTimeoutBeginCallback[] beginOperations, OperationEndCallback[] endOperations,
            AsyncCallback callback, object state) 
        { 
            return new ComposedAsyncResult(timeout, beginOperations, endOperations, callback, state);
        } 

        public static void EndComposeAsyncOperations(IAsyncResult result)
        {
            ComposedAsyncResult.End(result); 
        }
 
        public static TimeSpan RemainingTime(IAsyncResult result) 
        {
            return ((ComposedAsyncResult)result).RemainingTime(); 
        }

        class ComposedAsyncResult : AsyncResult
        { 
            OperationWithTimeoutBeginCallback[] beginOperations;
            bool completedSynchronously = true; 
            int currentOperation = 0; 
            OperationEndCallback[] endOperations;
            TimeoutHelper timeoutHelper; 
            static AsyncCallback onOperationCompleted = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OnOperationCompletedStatic));

            internal ComposedAsyncResult(
                TimeSpan timeout, OperationWithTimeoutBeginCallback[] beginOperations, OperationEndCallback[] endOperations, 
                AsyncCallback callback, object state)
                : base(callback, state) 
            { 
                this.timeoutHelper = new TimeoutHelper(timeout);
                this.beginOperations = beginOperations; 
                this.endOperations = endOperations;

                this.SkipToNextOperation();
 
                if (this.currentOperation < this.beginOperations.Length)
                { 
                    this.beginOperations[this.currentOperation](this.RemainingTime(), onOperationCompleted, this); 
                }
                else 
                {
                    Complete(this.completedSynchronously);
                }
            } 

            public TimeSpan RemainingTime() 
            { 
                return this.timeoutHelper.RemainingTime();
            } 

            internal static void End(IAsyncResult result)
            {
                AsyncResult.End(result); 
            }
 
            void OnOperationCompleted(IAsyncResult result) 
            {
                this.completedSynchronously = this.completedSynchronously && result.CompletedSynchronously; 

                Exception exception = null;
                try
                { 
                    this.endOperations[this.currentOperation](result);
                } 
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e))
                        throw;

                    exception = e; 
                }
                if (exception != null) 
                { 
                    Complete(this.completedSynchronously, exception);
                    return; 
                }

                this.currentOperation++;
                this.SkipToNextOperation(); 

                if (this.currentOperation < this.beginOperations.Length) 
                { 
                    try
                    { 
                        this.beginOperations[this.currentOperation](this.RemainingTime(), onOperationCompleted, this);
                    }
#pragma warning suppress 56500 // covered by FxCOP
                    catch (Exception e) 
                    {
                        if (DiagnosticUtility.IsFatal(e)) 
                            throw; 

                        exception = e; 
                    }
                    if (exception != null)
                    {
                        Complete(this.completedSynchronously, exception); 
                        return;
                    } 
                } 
                else
                { 
                    Complete(this.completedSynchronously);
                }
            }
 
            static void OnOperationCompletedStatic(IAsyncResult result)
            { 
                ((ComposedAsyncResult)(result.AsyncState)).OnOperationCompleted(result); 
            }
 
            void SkipToNextOperation()
            {
                while (this.currentOperation < this.beginOperations.Length)
                { 
                    if (this.beginOperations[this.currentOperation] != default(OperationWithTimeoutBeginCallback))
                    { 
                        return; 
                    }
 
                    this.currentOperation++;
                }
            }
        } 
    }
 
    sealed class Guard 
    {
        ManualResetEvent closeEvent; 
        int currentCount = 0;
        int maxCount;
        bool closed;
        object thisLock = new object(); 

        event WaitAsyncResult.SignaledHandler Signaled; 
 
        public Guard()
            : this(1) 
        {
        }

        public Guard(int maxCount) 
        {
            this.maxCount = maxCount; 
        } 

        public void Abort() 
        {
            this.closed = true;
        }
 
        public IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            bool complete = false; 
            WaitAsyncResult result = null;
 
            lock (this.thisLock)
            {
                if (this.closed || this.currentCount == 0)
                { 
                    complete = true;
                } 
                else 
                {
                    result = new WaitAsyncResult(timeout, true, callback, state); 
                    this.Signaled += result.OnSignaled;
                }

                this.closed = true; 
            }
 
            if (complete) 
            {
                return new CompletedAsyncResult(callback, state); 
            }
            else
            {
                result.Begin(); 
                return result;
            } 
        } 

        public void Close(TimeSpan timeout) 
        {
            lock (this.thisLock)
            {
                if (this.closed) 
                    return;
 
                this.closed = true; 

                if (this.currentCount > 0) 
                    this.closeEvent = new ManualResetEvent(false);
            }

            if (this.closeEvent != null) 
            {
                try 
                { 
                    if (!TimeoutHelper.WaitOne(this.closeEvent, timeout, false))
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TimeoutException(SR.GetString(SR.TimeoutOnOperation, timeout))); 
                }
                finally
                {
                    lock (this.thisLock) 
                    {
                        this.closeEvent.Close(); 
                        this.closeEvent = null; 
                    }
                } 
            }
        }

        public void EndClose(IAsyncResult result) 
        {
            if (result is CompletedAsyncResult) 
                CompletedAsyncResult.End(result); 
            else
                WaitAsyncResult.End(result); 
        }

        public bool Enter()
        { 
            lock (this.thisLock)
            { 
                if (this.closed) 
                    return false;
 
                if (this.currentCount == this.maxCount)
                    return false;

                this.currentCount++; 
                return true;
            } 
        } 

        public void Exit() 
        {
            WaitAsyncResult.SignaledHandler handler = null;

            lock (this.thisLock) 
            {
                this.currentCount--; 
 
                if (this.currentCount < 0)
                { 
                    DiagnosticUtility.DebugAssert("Exit can only be called after Enter.");
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
                }
 
                if (this.currentCount == 0)
                { 
                    if (this.closeEvent != null) 
                        this.closeEvent.Set();
 
                    handler = this.Signaled;
                }
            }
 
            if (handler != null)
                handler(); 
        } 
    }
 
    class InterruptibleTimer
    {
        WaitCallback callback;
        bool aborted = false; 
        TimeSpan defaultInterval;
        static WaitCallback onTimerElapsed = new WaitCallback(OnTimerElapsed); 
        bool set = false; 
        object state;
        object thisLock = new object(); 
        IOThreadTimer timer;

        public InterruptibleTimer(TimeSpan defaultInterval, WaitCallback callback, object state)
        { 
            if (callback == null)
            { 
                DiagnosticUtility.DebugAssert("Argument callback cannot be null."); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            } 

            this.defaultInterval = defaultInterval;
            this.callback = callback;
            this.state = state; 
        }
 
        object ThisLock 
        {
            get 
            {
                return this.thisLock;
            }
        } 

        public void Abort() 
        { 
            lock (this.ThisLock)
            { 
                this.aborted = true;

                if (this.set)
                { 
                    this.timer.Cancel();
                    this.set = false; 
                } 
            }
        } 

        public bool Cancel()
        {
            lock (this.ThisLock) 
            {
                if (this.aborted) 
                { 
                    return false;
                } 

                if (this.set)
                {
                    this.timer.Cancel(); 
                    this.set = false;
                    return true; 
                } 
                else
                { 
                    return false;
                }
            }
        } 

        void OnTimerElapsed() 
        { 
            lock (this.ThisLock)
            { 
                if (this.aborted)
                    return;

                this.set = false; 
            }
 
            callback(state); 
        }
 
        static void OnTimerElapsed(object state)
        {
            InterruptibleTimer interruptibleTimer = (InterruptibleTimer)state;
            interruptibleTimer.OnTimerElapsed(); 
        }
 
        public void Set() 
        {
            this.Set(this.defaultInterval); 
        }

        public void Set(TimeSpan interval)
        { 
            this.InternalSet(interval, false);
        } 
 
        public void SetIfNotSet()
        { 
            this.InternalSet(this.defaultInterval, true);
        }

        void InternalSet(TimeSpan interval, bool ifNotSet) 
        {
            lock (this.ThisLock) 
            { 
                if (this.aborted || (ifNotSet && this.set))
                    return; 

                if (this.timer == null)
                    this.timer = new IOThreadTimer(onTimerElapsed, this, true);
 
                this.timer.Set(interval);
                this.set = true; 
            } 
        }
    } 

    class InterruptibleWaitObject
    {
        bool aborted = false; 
        CommunicationObject communicationObject;
        ManualResetEvent handle; 
        bool set; 
        int syncWaiters;
        object thisLock = new object(); 
        bool throwTimeoutByDefault = true;

        public InterruptibleWaitObject(bool signaled): this(signaled, true)
        { 
        }
 
        public InterruptibleWaitObject(bool signaled, bool throwTimeoutByDefault) 
        {
            this.set = signaled; 
            this.throwTimeoutByDefault = throwTimeoutByDefault;
        }

        event WaitAsyncResult.AbortHandler Aborted; 
        event WaitAsyncResult.AbortHandler Faulted;
        event WaitAsyncResult.SignaledHandler Signaled; 
 
        public void Abort(CommunicationObject communicationObject)
        { 
            if (communicationObject == null)
            {
                DiagnosticUtility.DebugAssert("Argument communicationObject cannot be null.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            }
 
            lock (this.thisLock) 
            {
                if (this.aborted) 
                    return;

                this.communicationObject = communicationObject;
 
                this.aborted = true;
                InternalSet(); 
            } 

            WaitAsyncResult.AbortHandler handler = this.Aborted; 

            if (handler != null)
                handler(communicationObject);
        } 

        public void Fault(CommunicationObject communicationObject) 
        { 
            if (communicationObject == null)
            { 
                DiagnosticUtility.DebugAssert("Argument communicationObject cannot be null.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            }
 
            lock (this.thisLock)
            { 
                if (this.aborted) 
                    return;
 
                this.communicationObject = communicationObject;

                this.aborted = false;
                InternalSet(); 
            }
 
            WaitAsyncResult.AbortHandler handler = this.Faulted; 

            if (handler != null) 
                handler(communicationObject);
        }

        public IAsyncResult BeginWait(TimeSpan timeout, AsyncCallback callback, object state) 
        {
            return this.BeginWait(timeout, this.throwTimeoutByDefault, callback, state); 
        } 

        public IAsyncResult BeginWait(TimeSpan timeout, bool throwTimeoutException, AsyncCallback callback, object state) 
        {
            Exception e = null;

            lock (this.thisLock) 
            {
                if (!this.set) 
                { 
                    WaitAsyncResult result = new WaitAsyncResult(timeout, throwTimeoutException, callback, state);
 
                    this.Aborted += result.OnAborted;
                    this.Faulted += result.OnFaulted;
                    this.Signaled += result.OnSignaled;
                    result.Begin(); 
                    return result;
                } 
                else if (this.communicationObject != null) 
                {
                    e = this.GetException(); 
                }
            }

            if (e != null) 
            {
                DiagnosticUtility.ExceptionUtility.TraceHandledException(e, System.Diagnostics.TraceEventType.Error); 
            } 

            return new CompletedAsyncResult(e, callback, state); 
        }

        public IAsyncResult BeginTryWait(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            return this.BeginWait(timeout, false, callback, state);
        } 
 
        public void EndWait(IAsyncResult result)
        { 
            this.EndTryWait(result);
        }

        public bool EndTryWait(IAsyncResult result) 
        {
            if (result is CompletedAsyncResult) 
            { 
                CompletedAsyncResult.End(result);
                return true; 
            }
            else
            {
                return WaitAsyncResult.End(result); 
            }
        } 
 
        Exception GetException()
        { 
            if (this.communicationObject == null)
            {
                DiagnosticUtility.DebugAssert("Caller is attempting to retrieve an exception from a null communicationObject.");
            } 

            return this.aborted 
                ? this.communicationObject.CreateAbortedException() 
                : this.communicationObject.GetTerminalException();
        } 

        void InternalSet()
        {
            lock (this.thisLock) 
            {
                set = true; 
 
                if (this.handle != null)
                    this.handle.Set(); 
            }
        }

        public void Reset() 
        {
            lock (this.thisLock) 
            { 
                communicationObject = null;
                aborted = false; 
                set = false;

                if (this.handle != null)
                    this.handle.Reset(); 
            }
        } 
 
        public void Set()
        { 
            InternalSet();

            WaitAsyncResult.SignaledHandler handler = this.Signaled;
            if (handler != null) 
                handler();
        } 
 
        public bool Wait(TimeSpan timeout)
        { 
            return this.Wait(timeout, this.throwTimeoutByDefault);
        }

        public bool Wait(TimeSpan timeout, bool throwTimeoutException) 
        {
            lock (this.thisLock) 
            { 
                if (set)
                { 
                    if (this.communicationObject != null)
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(this.GetException());

                    return true; 
                }
 
                if (this.handle == null) 
                    this.handle = new ManualResetEvent(false);
 
                this.syncWaiters++;
            }

            try 
            {
                if (!TimeoutHelper.WaitOne(this.handle, timeout, false)) 
                { 
                    if (throwTimeoutException)
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TimeoutException(SR.GetString(SR.TimeoutOnOperation, timeout))); 
                    else
                        return false;
                }
            } 
            finally
            { 
                lock (this.thisLock) 
                {
                    // Last one out turns off the light. 
                    this.syncWaiters--;
                    if (this.syncWaiters == 0)
                    {
                        this.handle.Close(); 
                        this.handle = null;
                    } 
                } 
            }
 
            if (this.communicationObject != null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(this.GetException());

            return true; 
        }
    } 
 
    abstract class FaultHelper
    { 
        object thisLock = new object();

        protected FaultHelper()
        { 
        }
 
        protected object ThisLock 
        {
            get { return this.thisLock; } 
        }

        public abstract void Abort();
 
        public static bool AddressReply(Message message, Message faultMessage)
        { 
            try 
            {
                RequestReplyCorrelator.PrepareReply(faultMessage, message); 
            }
            catch (MessageHeaderException exception)
            {
                // ignore it - we don't need to correlate the reply if the MessageId header is bad 
                if (DiagnosticUtility.ShouldTraceInformation)
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information); 
            } 

            bool sendFault = true; 
            try
            {
                sendFault = RequestReplyCorrelator.AddressReply(faultMessage, message);
            } 
            catch (MessageHeaderException exception)
            { 
                // ignore it - we don't need to address the reply if the addressing headers are bad 
                if (DiagnosticUtility.ShouldTraceInformation)
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information); 
            }

            return sendFault;
        } 

        public abstract IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state); 
        public abstract void Close(TimeSpan timeout); 
        public abstract void EndClose(IAsyncResult result);
        public abstract void SendFaultAsync(IReliableChannelBinder binder, RequestContext requestContext, Message faultMessage); 
    }

    abstract class TypedFaultHelper : FaultHelper
    { 
        InterruptibleWaitObject closeHandle;
        TimeSpan defaultCloseTimeout; 
        TimeSpan defaultSendTimeout; 
        Dictionary faultList = new Dictionary();
        AsyncCallback onBinderCloseComplete; 
        AsyncCallback onSendFaultComplete;
        WaitCallback sendFaultCallback;

        protected TypedFaultHelper(TimeSpan defaultSendTimeout, TimeSpan defaultCloseTimeout) 
        {
            this.defaultSendTimeout = defaultSendTimeout; 
            this.defaultCloseTimeout = defaultCloseTimeout; 
        }
 
        public override void Abort()
        {
            Dictionary tempFaultList;
            InterruptibleWaitObject tempCloseHandle; 

            lock (this.ThisLock) 
            { 
                tempFaultList = this.faultList;
                this.faultList = null; 
                tempCloseHandle = this.closeHandle;
            }

            if ((tempFaultList == null) || (tempFaultList.Count == 0)) 
            {
                if (tempCloseHandle != null) 
                    tempCloseHandle.Set(); 
                return;
            } 

            foreach (KeyValuePair pair in tempFaultList)
            {
                this.AbortState(pair.Value); 
                pair.Key.Abort();
            } 
 
            if (tempCloseHandle != null)
                tempCloseHandle.Set(); 
        }

        void AbortBinder(IReliableChannelBinder binder)
        { 
            try
            { 
                binder.Abort(); 
            }
            finally 
            {
                this.RemoveBinder(binder);
            }
        } 

        void AsyncCloseBinder(IReliableChannelBinder binder) 
        { 
            if (this.onBinderCloseComplete == null)
                this.onBinderCloseComplete = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(this.OnBinderCloseComplete)); 

            IAsyncResult result = binder.BeginClose(this.defaultCloseTimeout, this.onBinderCloseComplete, binder);
            if (result.CompletedSynchronously)
                this.CompleteBinderClose(binder, result); 
        }
 
        protected abstract void AbortState(TState state); 

        void AfterClose() 
        {
            this.Abort();
        }
 
        bool BeforeClose()
        { 
            lock (this.ThisLock) 
            {
                if ((this.faultList == null) || (this.faultList.Count == 0)) 
                    return true;

                this.closeHandle = new InterruptibleWaitObject(false, false);
            } 

            return false; 
        } 

        public override IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state) 
        {
            if (this.BeforeClose())
                return new AlreadyClosedAsyncResult(callback, state);
            else 
                return this.closeHandle.BeginWait(timeout, callback, state);
        } 
 
        protected abstract IAsyncResult BeginSendFault(IReliableChannelBinder binder, TState state, TimeSpan timeout,
            AsyncCallback callback, object asyncState); 

        public override void Close(TimeSpan timeout)
        {
            if (this.BeforeClose()) 
                return;
 
            this.closeHandle.Wait(timeout); 
            this.AfterClose();
        } 

        void CompleteBinderClose(IReliableChannelBinder binder, IAsyncResult result)
        {
            try 
            {
                binder.EndClose(result); 
            } 
            finally
            { 
                this.RemoveBinder(binder);
            }
        }
 
        void CompleteSendFault(IReliableChannelBinder binder, TState state, IAsyncResult result)
        { 
            bool throwing = true; 

            try 
            {
                this.EndSendFault(binder, state, result);
                throwing = false;
            } 
            finally
            { 
                if (throwing) 
                {
                    this.AbortState(state); 
                    this.AbortBinder(binder);
                }
            }
 
            this.AsyncCloseBinder(binder);
        } 
 
        public override void EndClose(IAsyncResult result)
        { 
            if (result is AlreadyClosedAsyncResult)
                AlreadyClosedAsyncResult.End(result);
            else
                this.closeHandle.EndWait(result); 

            this.AfterClose(); 
        } 

        protected abstract void EndSendFault(IReliableChannelBinder binder, TState state, IAsyncResult result); 
        protected abstract TState GetState(RequestContext requestContext, Message faultMessage);

        void OnBinderCloseComplete(IAsyncResult result)
        { 
            if (result.CompletedSynchronously)
            { 
                return; 
            }
 
            IReliableChannelBinder binder = (IReliableChannelBinder)result.AsyncState;

            try
            { 
                this.CompleteBinderClose(binder, result);
            } 
            catch (Exception e) 
            {
                if (DiagnosticUtility.IsFatal(e)) 
                {
                    throw;
                }
 
                binder.HandleException(e);
            } 
        } 

        void OnSendFaultComplete(IAsyncResult result) 
        {
            if (result.CompletedSynchronously)
            {
                return; 
            }
 
            IReliableChannelBinder binder; 
            TState state;
 
            lock (this.ThisLock)
            {
                if (this.faultList == null)
                    return; 

                binder = (IReliableChannelBinder)result.AsyncState; 
                state = this.faultList[binder]; 
            }
 
            try
            {
                this.CompleteSendFault(binder, state, result);
            } 
            catch (Exception e)
            { 
                if (DiagnosticUtility.IsFatal(e)) 
                {
                    throw; 
                }

                binder.HandleException(e);
            } 
        }
 
        protected void RemoveBinder(IReliableChannelBinder binder) 
        {
            InterruptibleWaitObject tempCloseHandle; 

            lock (this.ThisLock)
            {
                if (this.faultList == null) 
                    return;
 
                this.faultList.Remove(binder); 
                if ((this.closeHandle == null) || (this.faultList.Count > 0))
                    return; 

                // Close has been called.
                this.faultList = null;
                tempCloseHandle = this.closeHandle; 
            }
 
            tempCloseHandle.Set(); 
        }
 
        protected void SendFault(IReliableChannelBinder binder, TState state)
        {
            IAsyncResult result;
            bool throwing = true; 

            try 
            { 
                result = this.BeginSendFault(binder, state, this.defaultSendTimeout, this.onSendFaultComplete, binder);
                throwing = false; 
            }
            finally
            {
                if (throwing) 
                {
                    this.AbortState(state); 
                    this.AbortBinder(binder); 
                }
            } 

            if (result.CompletedSynchronously)
                this.CompleteSendFault(binder, state, result);
        } 

        public override void SendFaultAsync(IReliableChannelBinder binder, RequestContext requestContext, Message faultMessage) 
        { 
            try
            { 
                bool abort = true;
                TState state = this.GetState(requestContext, faultMessage);

                lock (this.ThisLock) 
                {
                    if (this.faultList != null) 
                    { 
                        abort = false;
                        this.faultList.Add(binder, state); 

                        if (this.onSendFaultComplete == null)
                            this.onSendFaultComplete = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(this.OnSendFaultComplete));
                    } 
                }
 
                if (abort) 
                {
                    this.AbortState(state); 
                    binder.Abort();
                }
                else if (Thread.CurrentThread.IsThreadPoolThread)
                { 
                    this.SendFault(binder, state);
                } 
                else 
                {
                    if (this.sendFaultCallback == null) 
                        this.sendFaultCallback = new WaitCallback(this.SendFaultCallback);
                    IOThreadScheduler.ScheduleCallback(this.sendFaultCallback, binder);
                }
            } 
            catch (Exception e)
            { 
                if (DiagnosticUtility.IsFatal(e)) 
                {
                    throw; 
                }

                binder.HandleException(e);
            } 
        }
 
        void SendFaultCallback(object callbackState) 
        {
            IReliableChannelBinder binder; 
            TState state;

            lock (this.ThisLock)
            { 
                if (this.faultList == null)
                    return; 
 
                binder = (IReliableChannelBinder)callbackState;
                state = this.faultList[binder]; 
            }

            try
            { 
                this.SendFault(binder, state);
            } 
            catch (Exception e) 
            {
                if (DiagnosticUtility.IsFatal(e)) 
                {
                    throw;
                }
 
                binder.HandleException(e);
            } 
        } 

        class AlreadyClosedAsyncResult : CompletedAsyncResult 
        {
            public AlreadyClosedAsyncResult(AsyncCallback callback, object state)
                : base(callback, state)
            { 
            }
        } 
    } 

    struct FaultState 
    {
        Message faultMessage;
        RequestContext requestContext;
 
        public FaultState(RequestContext requestContext, Message faultMessage)
        { 
            this.requestContext = requestContext; 
            this.faultMessage = faultMessage;
        } 

        public Message FaultMessage { get { return this.faultMessage; } }
        public RequestContext RequestContext { get { return this.requestContext; } }
    } 

    class ReplyFaultHelper : TypedFaultHelper 
    { 
        public ReplyFaultHelper(TimeSpan defaultSendTimeout, TimeSpan defaultCloseTimeout)
            : base(defaultSendTimeout, defaultCloseTimeout) 
        {
        }

        protected override void AbortState(FaultState faultState) 
        {
            faultState.FaultMessage.Close(); 
            faultState.RequestContext.Abort(); 
        }
 
        protected override IAsyncResult BeginSendFault(IReliableChannelBinder binder, FaultState faultState,
            TimeSpan timeout, AsyncCallback callback, object state)
        {
            return faultState.RequestContext.BeginReply(faultState.FaultMessage, timeout, callback, state); 
        }
 
        protected override void EndSendFault(IReliableChannelBinder binder, FaultState faultState, IAsyncResult result) 
        {
            faultState.RequestContext.EndReply(result); 
            faultState.FaultMessage.Close();
        }

        protected override FaultState GetState(RequestContext requestContext, Message faultMessage) 
        {
            return new FaultState(requestContext, faultMessage); 
        } 

    } 

    class SendFaultHelper : TypedFaultHelper
    {
        public SendFaultHelper(TimeSpan defaultSendTimeout, TimeSpan defaultCloseTimeout) 
            : base(defaultSendTimeout, defaultCloseTimeout)
        { 
        } 

        protected override void AbortState(Message message) 
        {
            message.Close();
        }
 
        protected override IAsyncResult BeginSendFault(IReliableChannelBinder binder, Message message,
            TimeSpan timeout, AsyncCallback callback, object state) 
        { 
            return binder.BeginSend(message, timeout, callback, state);
        } 

        protected override void EndSendFault(IReliableChannelBinder binder, Message message, IAsyncResult result)
        {
            binder.EndSend(result); 
            message.Close();
        } 
 
        protected override Message GetState(RequestContext requestContext, Message faultMessage)
        { 
            return faultMessage;
        }
    }
 
    class ReliableChannelCloseAsyncResult : AsyncResult
    { 
        IReliableChannelBinder binder; 
        static AsyncCallback onBinderCloseComplete = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OnBinderCloseComplete));
        static AsyncCallback onComposeAsyncOperationsComplete = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OnComposeAsyncOperationsComplete)); 
        TimeoutHelper timeoutHelper;

        public ReliableChannelCloseAsyncResult(OperationWithTimeoutBeginCallback[] beginCallbacks,
            OperationEndCallback[] endCallbacks, IReliableChannelBinder binder, TimeSpan timeout, 
            AsyncCallback callback, object state)
            : base (callback, state) 
        { 
            this.binder = binder;
            this.timeoutHelper = new TimeoutHelper(timeout); 

            IAsyncResult result = OperationWithTimeoutComposer.BeginComposeAsyncOperations(timeoutHelper.RemainingTime(),
                beginCallbacks, endCallbacks, onComposeAsyncOperationsComplete, this);
 
            if (result.CompletedSynchronously)
            { 
                if (this.CompleteComposeAsyncOperations(result)) 
                {
                    this.Complete(true); 
                }
            }
        }
 
        bool CompleteComposeAsyncOperations(IAsyncResult result)
        { 
            OperationWithTimeoutComposer.EndComposeAsyncOperations(result); 

            result = this.binder.BeginClose(this.timeoutHelper.RemainingTime(), 
                MaskingMode.Handled, onBinderCloseComplete, this);

            if (result.CompletedSynchronously)
            { 
                this.binder.EndClose(result);
                return true; 
            } 

            return false; 
        }

        public static void End(IAsyncResult result)
        { 
            AsyncResult.End(result);
        } 
 
        static void OnBinderCloseComplete(IAsyncResult result)
        { 
            if (!result.CompletedSynchronously)
            {
                ReliableChannelCloseAsyncResult closeResult =
                    (ReliableChannelCloseAsyncResult)result.AsyncState; 
                Exception completeException = null;
 
                try 
                {
                    closeResult.binder.EndClose(result); 
                }
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e))
                        throw; 
 
                    completeException = e;
                } 

                closeResult.Complete(false, completeException);
            }
        } 

        static void OnComposeAsyncOperationsComplete(IAsyncResult result) 
        { 
            if (!result.CompletedSynchronously)
            { 
                ReliableChannelCloseAsyncResult closeResult =
                    (ReliableChannelCloseAsyncResult)result.AsyncState;

                bool complete = false; 
                Exception completeException = null;
 
                try 
                {
                    complete = closeResult.CompleteComposeAsyncOperations(result); 
                }
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e))
                        throw; 
 
                    completeException = e;
                } 

                if (complete || completeException != null)
                {
                    closeResult.Complete(false, completeException); 
                }
            } 
        } 
    }
 
    class ReliableChannelOpenAsyncResult : AsyncResult
    {
        IReliableChannelBinder binder;
        static AsyncCallback onBinderOpenComplete = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OnBinderOpenComplete)); 
        static AsyncCallback onSessionOpenComplete = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OnSessionOpenComplete));
        ChannelReliableSession session; 
        TimeoutHelper timeoutHelper; 

        public ReliableChannelOpenAsyncResult(IReliableChannelBinder binder, 
            ChannelReliableSession session, TimeSpan timeout, AsyncCallback callback, object state)
            : base(callback, state)
        {
            this.binder = binder; 
            this.session = session;
            this.timeoutHelper = new TimeoutHelper(timeout); 
 
            bool complete = false;
            bool throwing = true; 
            Exception completeException = null;

            try
            { 
                IAsyncResult result = this.binder.BeginOpen(timeoutHelper.RemainingTime(), onBinderOpenComplete, this);
                throwing = false; 
                if (result.CompletedSynchronously) 
                {
                    complete = this.CompleteBinderOpen(true, result); 
                }
            }
            catch (Exception e)
            { 
                if (DiagnosticUtility.IsFatal(e))
                    throw; 
 
                if (throwing || this.CloseBinder(completeException))
                    throw; 
            }
            finally
            {
                if (throwing) 
                    this.binder.Abort();
            } 
 
            if (complete)
                this.Complete(true); 
        }

        bool CloseBinder(Exception e)
        { 
            IAsyncResult result = this.binder.BeginClose(this.timeoutHelper.RemainingTime(),
                DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(this.OnBinderCloseComplete)), e); 
 
            if (result.CompletedSynchronously)
            { 
                this.binder.EndClose(result);
                return true;
            }
            else 
            {
                return false; 
            } 
        }
 
        void CloseBinderAndComplete(Exception e)
        {
            bool complete = true;
 
            try
            { 
                complete = this.CloseBinder(e); 
            }
            catch (Exception ex) 
            {
                if (DiagnosticUtility.IsFatal(ex))
                    throw;
                if (DiagnosticUtility.ShouldTraceInformation) 
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(ex, TraceEventType.Information);
            } 
 
            if (complete)
                this.Complete(false, e); 

        }

        bool CompleteBinderOpen(bool synchronous, IAsyncResult result) 
        {
            this.binder.EndOpen(result); 
            result = this.session.BeginOpen(this.timeoutHelper.RemainingTime(), 
                onSessionOpenComplete, this);
 
            if (result.CompletedSynchronously)
            {
                this.session.EndOpen(result);
                return true; 
            }
 
            return false; 
        }
 
        public static void End(IAsyncResult result)
        {
            AsyncResult.End(result);
        } 

        void OnBinderCloseComplete(IAsyncResult result) 
        { 
            if (!result.CompletedSynchronously)
            { 
                Exception completeException = (Exception)result.AsyncState;

                try
                { 
                    this.binder.EndClose(result);
                } 
                catch (Exception e) 
                {
                    if (DiagnosticUtility.IsFatal(e)) 
                        throw;
                    if (DiagnosticUtility.ShouldTraceInformation)
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                } 

                this.Complete(false, completeException); 
            } 
        }
 
        static void OnBinderOpenComplete(IAsyncResult result)
        {
            if (!result.CompletedSynchronously)
            { 
                ReliableChannelOpenAsyncResult openResult =
                    (ReliableChannelOpenAsyncResult)result.AsyncState; 
 
                bool complete = false;
                Exception completeException = null; 

                try
                {
                    complete = openResult.CompleteBinderOpen(false, result); 
                }
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e) 
                {
                    if (DiagnosticUtility.IsFatal(e)) 
                        throw;

                    completeException = e;
                } 

                if (complete) 
                    openResult.Complete(false, completeException); 
                else if (completeException != null)
                    openResult.CloseBinderAndComplete(completeException); 
            }
        }

        static void OnSessionOpenComplete(IAsyncResult result) 
        {
            if (!result.CompletedSynchronously) 
            { 
                ReliableChannelOpenAsyncResult openResult =
                    (ReliableChannelOpenAsyncResult)result.AsyncState; 

                Exception completeException = null;

                try 
                {
                    openResult.session.EndOpen(result); 
                } 
#pragma warning suppress 56500 // covered by FxCOP
                catch (Exception e) 
                {
                    if (DiagnosticUtility.IsFatal(e))
                        throw;
 
                    completeException = e;
                } 
 
                if (completeException != null)
                    openResult.CloseBinderAndComplete(completeException); 
                else
                    openResult.Complete(false);
            }
        } 
    }
 
 
    static class ReliableMessagingConstants
    { 
        static public TimeSpan UnknownInitiationTime = TimeSpan.FromSeconds(2);
        static public TimeSpan RequestorIterationTime = TimeSpan.FromSeconds(10);
        static public TimeSpan RequestorReceiveTime = TimeSpan.FromSeconds(10);
        static public int MaxSequenceRanges = 128; 
    }
 
    // This class and its derivates attempt to unify 3 similar request reply patterns. 
    // 1. Straightforward R/R pattern
    // 2. R/R pattern with binder and exception semantics on Open (CreateSequence) 
    // 3. TerminateSequence request - TerminateSequence response for R(Request|Reply)SC
    abstract class ReliableRequestor
    {
        InterruptibleWaitObject abortHandle = new InterruptibleWaitObject(false, false); 
        IReliableChannelBinder binder;
        bool isCreateSequence; 
        ActionHeader messageAction; 
        BodyWriter messageBody;
        WsrmMessageHeader messageHeader; 
        UniqueId messageId;
        MessageVersion messageVersion;
        TimeSpan originalTimeout;
        string timeoutString1Index; 

        public IReliableChannelBinder Binder 
        { 
            protected get { return this.binder; }
            set { this.binder = value; } 
        }

        public bool IsCreateSequence
        { 
            protected get { return this.isCreateSequence; }
            set { this.isCreateSequence = value; } 
        } 

        public ActionHeader MessageAction 
        {
            set { this.messageAction = value; }
        }
 
        public BodyWriter MessageBody
        { 
            set { this.messageBody = value; } 
        }
 
        public UniqueId MessageId
        {
            get { return this.messageId; }
        } 

        public WsrmMessageHeader MessageHeader 
        { 
            get { return this.messageHeader; }
            set { this.messageHeader = value; } 
        }

        public MessageVersion MessageVersion
        { 
            set { this.messageVersion = value; }
        } 
 
        public string TimeoutString1Index
        { 
            set { this.timeoutString1Index = value; }
        }

        public void Abort(CommunicationObject communicationObject) 
        {
            this.abortHandle.Abort(communicationObject); 
        } 

        Message CreateRequestMessage() 
        {
            Message request = Message.CreateMessage(this.messageVersion, this.messageAction, this.messageBody);
            request.Properties.AllowOutputBatching = false;
 
            if (this.messageHeader != null)
            { 
                request.Headers.Insert(0, this.messageHeader); 
            }
 
            if (this.messageId != null)
            {
                request.Headers.MessageId = this.messageId;
                RequestReplyCorrelator.PrepareRequest(request); 

                EndpointAddress address = this.binder.LocalAddress; 
 
                if (address == null)
                { 
                    request.Headers.ReplyTo = null;
                }
                else if (this.messageVersion.Addressing == AddressingVersion.WSAddressingAugust2004)
                { 
                    request.Headers.ReplyTo = address;
                } 
                else if (this.messageVersion.Addressing == AddressingVersion.WSAddressing10) 
                {
                    request.Headers.ReplyTo = address.IsAnonymous ? null : address; 
                }
                else
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                        new ProtocolException(SR.GetString(SR.AddressingVersionNotSupported, this.messageVersion.Addressing)));
                } 
            } 

            return request; 
        }

        bool EnsureChannel()
        { 
            if (this.IsCreateSequence)
            { 
                IClientReliableChannelBinder clientBinder = (IClientReliableChannelBinder)this.binder; 
                return clientBinder.EnsureChannelForRequest();
            } 
            else
            {
                return true;
            } 
        }
 
        public virtual void Fault(CommunicationObject communicationObject) 
        {
            this.abortHandle.Fault(communicationObject); 
        }

        public abstract WsrmMessageInfo GetInfo();
 
        TimeSpan GetNextRequestTimeout(TimeSpan remainingTimeout, out TimeoutHelper iterationTimeout, out bool lastIteration)
        { 
            iterationTimeout = new TimeoutHelper(ReliableMessagingConstants.RequestorIterationTime); 
            lastIteration = remainingTimeout <= ReliableMessagingConstants.RequestorIterationTime;
            iterationTimeout.SetDeadline(); 
            return remainingTimeout;
        }

        bool HandleException(Exception exception, bool lastIteration) 
        {
            if (this.IsCreateSequence) 
            { 
                if (exception is QuotaExceededException)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new CommunicationException(exception.Message, exception));
                }
 
                if (!this.binder.IsHandleable(exception) || (this.binder.State != CommunicationState.Opened)
                    || lastIteration) 
                { 
                    return false;
                } 

                return true;
            }
            else 
            {
                return this.binder.IsHandleable(exception); 
            } 
        }
 
        void ThrowTimeoutException()
        {
            if (this.timeoutString1Index != null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new TimeoutException(SR.GetString(this.timeoutString1Index, this.originalTimeout))); 
            } 
        }
 
        protected abstract Message OnRequest(Message request, TimeSpan timeout, bool last);
        protected abstract IAsyncResult OnBeginRequest(Message request, TimeSpan timeout,
            AsyncCallback callback, object state);
        protected abstract Message OnEndRequest(bool last, IAsyncResult result); 

        public Message Request(TimeSpan timeout) 
        { 
            this.originalTimeout = timeout;
            TimeoutHelper timeoutHelper = new TimeoutHelper(this.originalTimeout); 
            TimeoutHelper iterationTimeoutHelper;
            bool lastIteration;

            while (true) 
            {
                Message request = null; 
                Message reply = null; 
                bool requestCompleted = false;
                TimeSpan requestTimeout = this.GetNextRequestTimeout(timeoutHelper.RemainingTime(), 
                    out iterationTimeoutHelper, out lastIteration);

                try
                { 
                    if (this.EnsureChannel())
                    { 
                        request = this.CreateRequestMessage(); 
                        reply = this.OnRequest(request, requestTimeout, lastIteration);
                        requestCompleted = true; 
                    }
                }
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e) || !this.HandleException(e, lastIteration))
                    { 
                        throw; 
                    }
 
                    if (DiagnosticUtility.ShouldTraceInformation)
                    {
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                    } 
                }
                finally 
                { 
                    if (request != null)
                    { 
                        request.Close();
                    }
                }
 
                if (requestCompleted)
                { 
                    if (this.ValidateReply(reply)) 
                    {
                        return reply; 
                    }
                }

                if (lastIteration) 
                    break;
 
                this.abortHandle.Wait(iterationTimeoutHelper.RemainingTime()); 
            }
 
            this.ThrowTimeoutException();
            return null;
        }
 
        public IAsyncResult BeginRequest(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            return new RequestAsyncResult(this, timeout, callback, state); 
        }
 
        public Message EndRequest(IAsyncResult result)
        {
            return RequestAsyncResult.End(result);
        } 

        public abstract void SetInfo(WsrmMessageInfo info); 
 
        public void SetRequestResponsePattern()
        { 
            if (this.messageId != null)
            {
                DiagnosticUtility.DebugAssert("Initialize messageId only once.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            }
 
            this.messageId = new UniqueId(); 
        }
 
        bool ValidateReply(Message response)
        {
            if (this.messageId != null)
            { 
                // r/r pattern requires a response
                return response != null; 
            } 
            else
            { 
                return true;
            }
        }
 
        class RequestAsyncResult : AsyncResult
        { 
            static AsyncCallback requestCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(RequestCallback)); 
            static AsyncCallback waitCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(RequestAsyncResult.WaitCallback));
            TimeoutHelper iterationTimeoutHelper; 
            bool lastIteration = false;
            Message request;
            ReliableRequestor requestor;
            Message response; 
            TimeoutHelper timeoutHelper;
 
            public RequestAsyncResult(ReliableRequestor requestor, TimeSpan timeout, AsyncCallback callback, object state) 
                : base(callback, state)
            { 
                this.requestor = requestor;
                this.requestor.originalTimeout = timeout;
                this.timeoutHelper = new TimeoutHelper(this.requestor.originalTimeout);
 
                if (this.Request(null))
                { 
                    this.Complete(true); 
                }
            } 

            public static Message End(IAsyncResult result)
            {
                RequestAsyncResult requestResult = AsyncResult.End(result); 
                return requestResult.response;
            } 
 
            bool Request(IAsyncResult requestResult)
            { 
                while (true)
                {
                    bool requestCompleted = false;
                    bool disposeRequest = true; 

                    TimeSpan requestTimeout = (requestResult == null) 
                        ? this.requestor.GetNextRequestTimeout(this.timeoutHelper.RemainingTime(), 
                            out this.iterationTimeoutHelper, out this.lastIteration)
                        : TimeSpan.Zero; 

                    try
                    {
                        if (requestResult == null) 
                        {
                            if (this.requestor.EnsureChannel()) 
                            { 
                                this.request = this.requestor.CreateRequestMessage();
                                requestResult = this.requestor.OnBeginRequest(this.request, requestTimeout, 
                                    requestCallback, this);

                                if (!requestResult.CompletedSynchronously)
                                { 
                                    disposeRequest = false;
                                    return false; 
                                } 
                            }
                        } 

                        if (requestResult != null)
                        {
                            this.response = this.requestor.OnEndRequest(this.lastIteration, requestResult); 
                            requestCompleted = true;
                        } 
                    } 
                    catch (Exception e)
                    { 
                        if (DiagnosticUtility.IsFatal(e) || !this.requestor.HandleException(e, lastIteration))
                        {
                            throw;
                        } 

                        if (DiagnosticUtility.ShouldTraceInformation) 
                        { 
                            DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                        } 
                    }
                    finally
                    {
                        if (disposeRequest && this.request != null) 
                        {
                            this.request.Close(); 
                            this.request = null; 
                        }
 
                        requestResult = null;
                    }

                    if (requestCompleted) 
                    {
                        if (this.requestor.ValidateReply(this.response)) 
                        { 
                            return true;
                        } 
                    }

                    if (this.lastIteration)
                    { 
                        break;
                    } 
 
                    IAsyncResult waitResult = this.requestor.abortHandle.BeginWait(
                        iterationTimeoutHelper.RemainingTime(), waitCallback, this); 

                    if (!waitResult.CompletedSynchronously)
                    {
                        return false; 
                    }
                    else 
                    { 
                        this.requestor.abortHandle.EndWait(waitResult);
                    } 
                }

                this.requestor.ThrowTimeoutException();
                return true; 
            }
 
            static void RequestCallback(IAsyncResult result) 
            {
                if (!result.CompletedSynchronously) 
                {
                    RequestAsyncResult requestResult = (RequestAsyncResult)result.AsyncState;
                    bool complete;
                    Exception completeException; 

                    try 
                    { 
                        complete = requestResult.Request(result);
                        completeException = null; 
                    }
                    catch (Exception e)
                    {
                        if (DiagnosticUtility.IsFatal(e)) 
                        {
                            throw; 
                        } 

                        complete = true; 
                        completeException = e;
                    }

                    if (complete) 
                    {
                        requestResult.Complete(false, completeException); 
                    } 
                }
            } 

            bool EndWait(IAsyncResult result)
            {
                this.requestor.abortHandle.EndWait(result); 
                return this.Request(null);
            } 
 
            static void WaitCallback(IAsyncResult result)
            { 
                if (!result.CompletedSynchronously)
                {
                    RequestAsyncResult requestResult = (RequestAsyncResult)result.AsyncState;
                    bool complete; 
                    Exception completeException;
 
                    try 
                    {
                        complete = requestResult.EndWait(result); 
                        completeException = null;
                    }
                    catch (Exception e)
                    { 
                        if (DiagnosticUtility.IsFatal(e))
                        { 
                            throw; 
                        }
 
                        complete = true;
                        completeException = e;
                    }
 
                    if (complete)
                    { 
                        requestResult.Complete(false, completeException); 
                    }
                } 
            }
        }
    }
 
    sealed class RequestReliableRequestor : ReliableRequestor
    { 
        bool replied = false; 
        WsrmMessageInfo replyInfo;
        object thisLock = new object(); 

        IClientReliableChannelBinder ClientBinder
        {
            get { return (IClientReliableChannelBinder)this.Binder; } 
        }
 
        object ThisLock 
        {
            get { return this.thisLock; } 
        }

        public override WsrmMessageInfo GetInfo()
        { 
            return this.replyInfo;
        } 
 
        Message GetReply(Message reply, bool last)
        { 
            lock (this.ThisLock)
            {
                if (reply != null && this.replyInfo != null)
                { 
                    this.replyInfo = null;
                } 
                else if (reply == null && this.replyInfo != null) 
                {
                    reply = this.replyInfo.Message; 
                }

                if (reply != null || last)
                { 
                    this.replied = true;
                } 
            } 

            return reply; 
        }

        protected override Message OnRequest(Message request, TimeSpan timeout, bool last)
        { 
            return this.GetReply(this.ClientBinder.Request(request, timeout, MaskingMode.None), last);
        } 
 
        protected override IAsyncResult OnBeginRequest(Message request, TimeSpan timeout, AsyncCallback callback, object state)
        { 
            return this.ClientBinder.BeginRequest(request, timeout, MaskingMode.None, callback, state);
        }

        protected override Message OnEndRequest(bool last, IAsyncResult result) 
        {
            return this.GetReply(this.ClientBinder.EndRequest(result), last); 
        } 

        public override void SetInfo(WsrmMessageInfo info) 
        {
            lock (this.ThisLock)
            {
                if (!this.replied && this.replyInfo == null) 
                {
                    this.replyInfo = info; 
                } 
            }
        } 
    }

    sealed class SendReceiveReliableRequestor : ReliableRequestor
    { 
        bool timeoutIsSafe;
 
        public bool TimeoutIsSafe 
        {
            set { this.timeoutIsSafe = value; } 
        }

        public override WsrmMessageInfo GetInfo()
        { 
            DiagnosticUtility.DebugAssert("Not Supported.");
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
        } 

        TimeSpan GetReceiveTimeout(TimeSpan timeoutRemaining) 
        {
            if ((timeoutRemaining < ReliableMessagingConstants.RequestorReceiveTime) || !this.timeoutIsSafe)
            {
                return timeoutRemaining; 
            }
            else 
            { 
                return ReliableMessagingConstants.RequestorReceiveTime;
            } 
        }

        protected override Message OnRequest(Message request, TimeSpan timeout, bool last)
        { 
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
 
            this.Binder.Send(request, timeoutHelper.RemainingTime(), MaskingMode.None); 
            TimeSpan receiveTimeout = this.GetReceiveTimeout(timeoutHelper.RemainingTime());
 
            RequestContext requestContext;
            this.Binder.TryReceive(receiveTimeout, out requestContext, MaskingMode.None);
            return (requestContext != null) ? requestContext.RequestMessage : null;
        } 

        protected override IAsyncResult OnBeginRequest(Message request, TimeSpan timeout, AsyncCallback callback, object state) 
        { 
            return new SendReceiveAsyncResult(this, request, timeout, callback, state);
        } 

        protected override Message OnEndRequest(bool last, IAsyncResult result)
        {
            return SendReceiveAsyncResult.End(result); 
        }
 
        public override void SetInfo(WsrmMessageInfo info) 
        {
            DiagnosticUtility.DebugAssert("Not Supported."); 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
        }

        class SendReceiveAsyncResult : AsyncResult 
        {
            static AsyncCallback sendCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(SendCallback)); 
            static AsyncCallback tryReceiveCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(TryReceiveCallback)); 

            Message request; 
            SendReceiveReliableRequestor requestor;
            Message response;
            TimeoutHelper timeoutHelper;
 
            internal SendReceiveAsyncResult(SendReceiveReliableRequestor requestor, Message request, TimeSpan timeout,
                AsyncCallback callback, object state) 
                : base(callback, state) 
            {
                this.requestor = requestor; 
                this.request = request;
                this.timeoutHelper = new TimeoutHelper(timeout);

                if (this.BeginSend()) 
                {
                    this.Complete(true); 
                } 
            }
 
            bool BeginSend()
            {
                IAsyncResult sendResult = this.requestor.Binder.BeginSend(this.request,
                    this.timeoutHelper.RemainingTime(), MaskingMode.None, sendCallback, this); 

                if (sendResult.CompletedSynchronously) 
                { 
                    return this.EndSend(sendResult);
                } 
                else
                {
                    return false;
                } 
            }
 
            public static Message End(IAsyncResult result) 
            {
                SendReceiveAsyncResult sendReceiveResult = AsyncResult.End(result); 
                return sendReceiveResult.response;
            }

            bool EndSend(IAsyncResult result) 
            {
                this.requestor.Binder.EndSend(result); 
 
                TimeSpan receiveTimeout = this.requestor.GetReceiveTimeout(this.timeoutHelper.RemainingTime());
                IAsyncResult tryReceiveResult = this.requestor.Binder.BeginTryReceive(receiveTimeout, 
                    MaskingMode.None, tryReceiveCallback, this);

                if (tryReceiveResult.CompletedSynchronously)
                { 
                    return this.EndTryReceive(tryReceiveResult);
                } 
                else 
                {
                    return false; 
                }
            }

            bool EndTryReceive(IAsyncResult result) 
            {
                RequestContext requestContext; 
                this.requestor.Binder.EndTryReceive(result, out requestContext); 
                this.response = (requestContext != null) ? requestContext.RequestMessage : null;
                return true; 
            }

            static void SendCallback(IAsyncResult result)
            { 
                if (!result.CompletedSynchronously)
                { 
                    SendReceiveAsyncResult sendReceiveResult = (SendReceiveAsyncResult)result.AsyncState; 
                    Exception completeException;
                    bool complete = false; 

                    try
                    {
                        complete = sendReceiveResult.EndSend(result); 
                        completeException = null;
                    } 
                    catch (Exception e) 
                    {
                        if (DiagnosticUtility.IsFatal(e)) 
                        {
                            throw;
                        }
 
                        complete = true;
                        completeException = e; 
                    } 

                    if (complete) 
                    {
                        sendReceiveResult.Complete(false, completeException);
                    }
                } 
            }
 
            static void TryReceiveCallback(IAsyncResult result) 
            {
                if (!result.CompletedSynchronously) 
                {
                    SendReceiveAsyncResult sendReceiveResult = (SendReceiveAsyncResult)result.AsyncState;
                    Exception completeException;
                    bool complete = false; 

                    try 
                    { 
                        complete = sendReceiveResult.EndTryReceive(result);
                        completeException = null; 
                    }
                    catch (Exception e)
                    {
                        if (DiagnosticUtility.IsFatal(e)) 
                        {
                            throw; 
                        } 

                        complete = true; 
                        completeException = e;
                    }

                    if (complete) 
                    {
                        sendReceiveResult.Complete(false, completeException); 
                    } 
                }
            } 
        }
    }

    sealed class SendWaitReliableRequestor : ReliableRequestor 
    {
        bool replied = false; 
        InterruptibleWaitObject replyHandle = new InterruptibleWaitObject(false, true); 
        WsrmMessageInfo replyInfo;
        Message request; 
        object thisLock = new object();

        object ThisLock
        { 
            get { return this.thisLock; }
        } 
 
        public override void Fault(CommunicationObject communicationObject)
        { 
            this.replied = true;
            this.replyHandle.Fault(communicationObject);
            base.Fault(communicationObject);
        } 

        public override WsrmMessageInfo GetInfo() 
        { 
            return this.replyInfo;
        } 

        Message GetReply(bool last)
        {
            lock (this.ThisLock) 
            {
                if (this.replyInfo != null) 
                { 
                    this.replied = true;
                    return this.replyInfo.Message; 
                }
                else if (last)
                {
                    this.replied = true; 
                }
            } 
 
            return null;
        } 

        TimeSpan GetWaitTimeout(TimeSpan timeoutRemaining)
        {
            if ((timeoutRemaining < ReliableMessagingConstants.RequestorReceiveTime)) 
            {
                return timeoutRemaining; 
            } 
            else
            { 
                return ReliableMessagingConstants.RequestorReceiveTime;
            }
        }
 
        protected override Message OnRequest(Message request, TimeSpan timeout, bool last)
        { 
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
            this.Binder.Send(request, timeoutHelper.RemainingTime(), MaskingMode.None);
            TimeSpan waitTimeout = this.GetWaitTimeout(timeoutHelper.RemainingTime()); 
            this.replyHandle.Wait(waitTimeout);
            return this.GetReply(last);
        }
 
        protected override IAsyncResult OnBeginRequest(Message request, TimeSpan timeout, AsyncCallback callback, object state)
        { 
            this.request = request; 

            return OperationWithTimeoutComposer.BeginComposeAsyncOperations(timeout, 
                new OperationWithTimeoutBeginCallback[] {
                    new OperationWithTimeoutBeginCallback(BeginSend),
                    new OperationWithTimeoutBeginCallback(BeginWait) },
                new OperationEndCallback[] { 
                    new OperationEndCallback(EndSend),
                    new OperationEndCallback(EndWait) }, 
                callback, state); 
        }
 
        protected override Message OnEndRequest(bool last, IAsyncResult result)
        {
            OperationWithTimeoutComposer.EndComposeAsyncOperations(result);
            return this.GetReply(last); 
        }
 
        IAsyncResult BeginSend(TimeSpan timeout, AsyncCallback callback, object state) 
        {
            try 
            {
                return this.Binder.BeginSend(this.request, timeout, MaskingMode.None, callback, state);
            }
            finally 
            {
                this.request = null; 
            } 
        }
 
        void EndSend(IAsyncResult result)
        {
            this.Binder.EndSend(result);
        } 

        public override void SetInfo(WsrmMessageInfo info) 
        { 
            lock (this.ThisLock)
            { 
                if (this.replied || this.replyInfo != null)
                {
                    return;
                } 

                this.replyInfo = info; 
            } 

            this.replyHandle.Set(); 
        }

        IAsyncResult BeginWait(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            TimeSpan waitTimeout = this.GetWaitTimeout(timeout);
            return this.replyHandle.BeginWait(waitTimeout, callback, state); 
        } 

        void EndWait(IAsyncResult result) 
        {
            this.replyHandle.EndWait(result);
        }
    } 

    abstract class ReliableOutputAsyncResult : AsyncResult 
    { 
        IReliableChannelBinder binder;
        Exception handledException; 
        MaskingMode maskingMode;
        MessageAttemptInfo messageAttemptInfo;
        static AsyncCallback operationCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OperationCallback));
        bool saveHandledException; 

        protected ReliableOutputAsyncResult(AsyncCallback callback, object state) 
            : base(callback, state) 
        {
        } 

        public IReliableChannelBinder Binder
        {
            protected get { return this.binder; } 
            set { this.binder = value; }
        } 
 
        protected Exception HandledException
        { 
            get { return this.handledException; }
        }

        public MaskingMode MaskingMode 
        {
            get { return this.maskingMode; } 
            set { this.maskingMode = value; } 
        }
 
        public MessageAttemptInfo MessageAttemptInfo
        {
            get { return this.messageAttemptInfo; }
            set { this.messageAttemptInfo = value; } 
        }
 
        public Message Message 
        {
            protected get { return this.messageAttemptInfo.Message; } 
            set { this.messageAttemptInfo = new MessageAttemptInfo(value, 0, 0, null); }
        }

        public bool SaveHandledException 
        {
            set { this.saveHandledException = value; } 
        } 

        public void Begin(TimeSpan timeout) 
        {
            bool complete;

            if (this.saveHandledException) 
            {
                complete = this.BeginInternal(timeout); 
            } 
            else
            { 
                try
                {
                    complete = this.BeginInternal(timeout);
                } 
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e) || !this.HandleException(e)) 
                    {
                        throw; 
                    }

                    complete = true;
                } 
            }
 
            if (complete) 
            {
                this.Complete(true); 
            }
        }

        bool BeginInternal(TimeSpan timeout) 
        {
            bool closeMessage = true; 
 
            try
            { 
                IAsyncResult operationResult = this.BeginOperation(timeout, operationCallback, this);

                if (operationResult.CompletedSynchronously)
                { 
                    this.EndOperation(operationResult);
                    return true; 
                } 
                else
                { 
                    closeMessage = false;
                    return false;
                }
            } 
            finally
            { 
                if (closeMessage) 
                {
                    this.Message.Close(); 
                }
            }
        }
 
        protected abstract IAsyncResult BeginOperation(TimeSpan timeout, AsyncCallback callback, object state);
        protected abstract void EndOperation(IAsyncResult result); 
 
        static void OperationCallback(IAsyncResult result)
        { 
            if (!result.CompletedSynchronously)
            {
                ReliableOutputAsyncResult outputResult = (ReliableOutputAsyncResult)result.AsyncState;
                Exception completeException = null; 

                try 
                { 
                    outputResult.EndOperation(result);
                } 
                catch (Exception e)
                {
                    if (DiagnosticUtility.IsFatal(e))
                    { 
                        throw;
                    } 
 
                    if (!outputResult.HandleException(e))
                    { 
                        completeException = e;
                    }
                }
                finally 
                {
                    outputResult.Message.Close(); 
                } 

                outputResult.Complete(false, completeException); 
            }
        }

        bool HandleException(Exception e) 
        {
            if (this.saveHandledException && this.Binder.IsHandleable(e)) 
            { 
                this.handledException = e;
                return true; 
            }
            else
            {
                return false; 
            }
        } 
    } 

    class ReliableBinderSendAsyncResult : ReliableOutputAsyncResult 
    {
        public ReliableBinderSendAsyncResult(AsyncCallback callback, object state)
            : base(callback, state)
        { 
        }
 
        public static void End(IAsyncResult result) 
        {
            Exception handledException; 
            End(result, out handledException);
        }

        public static void End(IAsyncResult result, out Exception handledException) 
        {
            ReliableBinderSendAsyncResult sendResult = AsyncResult.End(result); 
            handledException = sendResult.HandledException; 
        }
 
        protected override IAsyncResult BeginOperation(TimeSpan timeout, AsyncCallback callback,
            object state)
        {
            return this.Binder.BeginSend(this.Message, timeout, this.MaskingMode, callback, state); 
        }
 
        protected override void EndOperation(IAsyncResult result) 
        {
            this.Binder.EndSend(result); 
        }
    }

    class ReliableBinderRequestAsyncResult : ReliableOutputAsyncResult 
    {
        Message reply; 
 
        public ReliableBinderRequestAsyncResult(AsyncCallback callback, object state)
            : base(callback, state) 
        {
        }

        protected IClientReliableChannelBinder ClientBinder 
        {
            get { return (IClientReliableChannelBinder)this.Binder; } 
        } 

        protected Message Reply 
        {
            get { return this.reply; }
        }
 
        public static Message End(IAsyncResult result)
        { 
            Exception handledException; 
            return End(result, out handledException);
        } 

        public static Message End(IAsyncResult result, out Exception handledException)
        {
            ReliableBinderRequestAsyncResult requestResult = AsyncResult.End(result); 
            handledException = requestResult.HandledException;
            return requestResult.reply; 
        } 

        protected override IAsyncResult BeginOperation(TimeSpan timeout, AsyncCallback callback, 
            object state)
        {
            return this.ClientBinder.BeginRequest(this.Message, timeout, this.MaskingMode, callback, state);
        } 

        protected override void EndOperation(IAsyncResult result) 
        { 
            this.reply = this.ClientBinder.EndRequest(result);
        } 
    }

    class WaitAsyncResult : AsyncResult
    { 
        bool completed;
        bool throwTimeoutException; 
        bool timedOut; 
        TimeSpan timeout;
        IOThreadTimer timer; 
        object thisLock = new object();

        public delegate void AbortHandler(CommunicationObject communicationObject);
        public delegate void SignaledHandler(); 

        public WaitAsyncResult(TimeSpan timeout, bool throwTimeoutException, AsyncCallback callback, object state) 
            : base(callback, state) 
        {
            this.timeout = timeout; 
            this.throwTimeoutException = throwTimeoutException;
        }

        public void Begin() 
        {
            lock (this.thisLock) 
            { 
                if (this.completed)
                    return; 

                if (this.timeout != TimeSpan.MaxValue)
                {
                    this.timer = new IOThreadTimer(OnTimerElapsed, null, true); 
                    this.timer.Set(this.timeout);
                } 
            } 
        }
 
        public static bool End(IAsyncResult result)
        {
            return !AsyncResult.End(result).timedOut;
        } 

        protected virtual string GetTimeoutString(TimeSpan timeout) 
        { 
            return SR.GetString(SR.TimeoutOnOperation, timeout);
        } 

        public void OnAborted(CommunicationObject communicationObject)
        {
            if (this.ShouldComplete(false)) 
                Complete(false, communicationObject.CreateClosedException());
        } 
 
        public void OnFaulted(CommunicationObject communicationObject)
        { 
            if (this.ShouldComplete(false))
                Complete(false, communicationObject.GetTerminalException());
        }
 
        public void OnSignaled()
        { 
            if (this.ShouldComplete(false)) 
                Complete(false);
        } 

        protected virtual void OnTimerElapsed(object state)
        {
            if (this.ShouldComplete(true)) 
            {
                if (this.throwTimeoutException) 
                    Complete(false, new TimeoutException(this.GetTimeoutString(this.timeout))); 
                else
                    Complete(false); 
            }
        }

        bool ShouldComplete(bool timedOut) 
        {
            lock (this.thisLock) 
            { 
                if (!this.completed)
                { 
                    this.completed = true;
                    this.timedOut = timedOut;
                    if (!timedOut && (this.timer != null))
                    { 
                        this.timer.Cancel();
                    } 
 
                    return true;
                } 
            }

            return false;
        } 
    }
 
    abstract class WsrmIndex 
    {
        static WsrmFeb2005Index wsAddressingAug2004WSReliableMessagingFeb2005; 
        static WsrmFeb2005Index wsAddressing10WSReliableMessagingFeb2005;
        static Wsrm11Index wsAddressingAug2004WSReliableMessaging11;
        static Wsrm11Index wsAddressing10WSReliableMessaging11;
 
        internal static ActionHeader GetAckRequestedActionHeader(AddressingVersion addressingVersion,
            ReliableMessagingVersion reliableMessagingVersion) 
        { 
            return GetActionHeader(addressingVersion, reliableMessagingVersion, WsrmFeb2005Strings.AckRequested);
        } 

        protected abstract ActionHeader GetActionHeader(string element);

        static ActionHeader GetActionHeader(AddressingVersion addressingVersion, 
            ReliableMessagingVersion reliableMessagingVersion, string element)
        { 
            WsrmIndex cache = null; 

            if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005) 
            {
                if (addressingVersion == AddressingVersion.WSAddressingAugust2004)
                {
                    if (wsAddressingAug2004WSReliableMessagingFeb2005 == null) 
                    {
                        wsAddressingAug2004WSReliableMessagingFeb2005 = new WsrmFeb2005Index(addressingVersion); 
                    } 

                    cache = wsAddressingAug2004WSReliableMessagingFeb2005; 
                }
                else if (addressingVersion == AddressingVersion.WSAddressing10)
                {
                    if (wsAddressing10WSReliableMessagingFeb2005 == null) 
                    {
                        wsAddressing10WSReliableMessagingFeb2005 = new WsrmFeb2005Index(addressingVersion); 
                    } 

                    cache = wsAddressing10WSReliableMessagingFeb2005; 
                }
            }
            else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
            { 
                if (addressingVersion == AddressingVersion.WSAddressingAugust2004)
                { 
                    if (wsAddressingAug2004WSReliableMessaging11 == null) 
                    {
                        wsAddressingAug2004WSReliableMessaging11 = new Wsrm11Index(addressingVersion); 
                    }

                    cache = wsAddressingAug2004WSReliableMessaging11;
                } 
                else if (addressingVersion == AddressingVersion.WSAddressing10)
                { 
                    if (wsAddressing10WSReliableMessaging11 == null) 
                    {
                        wsAddressing10WSReliableMessaging11 = new Wsrm11Index(addressingVersion); 
                    }

                    cache = wsAddressing10WSReliableMessaging11;
                } 
            }
            else 
            { 
                DiagnosticUtility.DebugAssert("Reliable messaging version not supported.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            }

            if (cache == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ProtocolException(SR.GetString(SR.AddressingVersionNotSupported, addressingVersion))); 
            } 

            return cache.GetActionHeader(element); 
        }

        internal static ActionHeader GetCloseSequenceActionHeader(AddressingVersion addressingVersion)
        { 
            return GetActionHeader(addressingVersion, ReliableMessagingVersion.WSReliableMessaging11, Wsrm11Strings.CloseSequence);
        } 
 
        internal static ActionHeader GetCloseSequenceResponseActionHeader(AddressingVersion addressingVersion)
        { 
            return GetActionHeader(addressingVersion, ReliableMessagingVersion.WSReliableMessaging11, Wsrm11Strings.CloseSequenceResponse);
        }

        internal static ActionHeader GetCreateSequenceActionHeader(AddressingVersion addressingVersion, 
            ReliableMessagingVersion reliableMessagingVersion)
        { 
            return GetActionHeader(addressingVersion, reliableMessagingVersion, WsrmFeb2005Strings.CreateSequence); 
        }
 
        internal static string GetCreateSequenceActionString(ReliableMessagingVersion reliableMessagingVersion)
        {
            if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
            { 
                return WsrmFeb2005Strings.CreateSequenceAction;
            } 
            else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11) 
            {
                return Wsrm11Strings.CreateSequenceAction; 
            }
            else
            {
                DiagnosticUtility.DebugAssert("Reliable messaging version not supported."); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            } 
        } 

        internal static XmlDictionaryString GetCreateSequenceResponseAction(ReliableMessagingVersion reliableMessagingVersion) 
        {
            if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
            {
                return XD.WsrmFeb2005Dictionary.CreateSequenceResponseAction; 
            }
            else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11) 
            { 
                return DXD.Wsrm11Dictionary.CreateSequenceResponseAction;
            } 
            else
            {
                DiagnosticUtility.DebugAssert("Reliable messaging version not supported.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            }
        } 
 
        internal static string GetCreateSequenceResponseActionString(ReliableMessagingVersion reliableMessagingVersion)
        { 
            if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
            {
                return WsrmFeb2005Strings.CreateSequenceResponseAction;
            } 
            else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
            { 
                return Wsrm11Strings.CreateSequenceResponseAction; 
            }
            else 
            {
                DiagnosticUtility.DebugAssert("Reliable messaging version not supported.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            } 
        }
 
        internal static string GetFaultActionString(AddressingVersion addressingVersion, 
            ReliableMessagingVersion reliableMessagingVersion)
        { 
            if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
            {
                return addressingVersion.DefaultFaultAction;
            } 
            else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
            { 
                return Wsrm11Strings.FaultAction; 
            }
            else 
            {
                DiagnosticUtility.DebugAssert("Reliable messaging version not supported.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            } 
        }
 
        internal static XmlDictionaryString GetNamespace(ReliableMessagingVersion reliableMessagingVersion) 
        {
            if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005) 
            {
                return XD.WsrmFeb2005Dictionary.Namespace;
            }
            else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11) 
            {
                return DXD.Wsrm11Dictionary.Namespace; 
            } 
            else
            { 
                DiagnosticUtility.DebugAssert("Reliable messaging version not supported.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            }
        } 

        internal static string GetNamespaceString(ReliableMessagingVersion reliableMessagingVersion) 
        { 
            if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
            { 
                return WsrmFeb2005Strings.Namespace;
            }
            else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
            { 
                return Wsrm11Strings.Namespace;
            } 
            else 
            {
                DiagnosticUtility.DebugAssert("Reliable messaging version not supported."); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            }
        }
 
        internal static ActionHeader GetSequenceAcknowledgementActionHeader(AddressingVersion addressingVersion,
            ReliableMessagingVersion reliableMessagingVersion) 
        { 
            return GetActionHeader(addressingVersion, reliableMessagingVersion, WsrmFeb2005Strings.SequenceAcknowledgement);
        } 

        internal static string GetSequenceAcknowledgementActionString(ReliableMessagingVersion reliableMessagingVersion)
        {
            if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005) 
            {
                return WsrmFeb2005Strings.SequenceAcknowledgementAction; 
            } 
            else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
            { 
                return Wsrm11Strings.SequenceAcknowledgementAction;
            }
            else
            { 
                DiagnosticUtility.DebugAssert("Reliable messaging version not supported.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            } 
        }
 
        internal static MessagePartSpecification GetSignedReliabilityMessageParts(
            ReliableMessagingVersion reliableMessagingVersion)
        {
            if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005) 
            {
                return WsrmFeb2005Index.SignedReliabilityMessageParts; 
            } 
            else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
            { 
                return Wsrm11Index.SignedReliabilityMessageParts;
            }
            else
            { 
                DiagnosticUtility.DebugAssert("Reliable messaging version not supported.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            } 
        }
 
        internal static ActionHeader GetTerminateSequenceActionHeader(AddressingVersion addressingVersion,
            ReliableMessagingVersion reliableMessagingVersion)
        {
            return GetActionHeader(addressingVersion, reliableMessagingVersion, WsrmFeb2005Strings.TerminateSequence); 
        }
 
        internal static string GetTerminateSequenceActionString(ReliableMessagingVersion reliableMessagingVersion) 
        {
            if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005) 
            {
                return WsrmFeb2005Strings.TerminateSequenceAction;
            }
            else if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11) 
            {
                return Wsrm11Strings.TerminateSequenceAction; 
            } 
            else
            { 
                DiagnosticUtility.DebugAssert("Reliable messaging version not supported.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            }
        } 

        internal static string GetTerminateSequenceResponseActionString(ReliableMessagingVersion reliableMessagingVersion) 
        { 
            if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
            { 
                return Wsrm11Strings.TerminateSequenceResponseAction;
            }
            else
            { 
                DiagnosticUtility.DebugAssert("Reliable messaging version not supported.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            } 
        }
 
        internal static ActionHeader GetTerminateSequenceResponseActionHeader(AddressingVersion addressingVersion)
        {
            return GetActionHeader(addressingVersion, ReliableMessagingVersion.WSReliableMessaging11,
                Wsrm11Strings.TerminateSequenceResponse); 
        }
    } 
 
    class Wsrm11Index : WsrmIndex
    { 
        static MessagePartSpecification signedReliabilityMessageParts;

        ActionHeader ackRequestedActionHeader;
        AddressingVersion addressingVersion; 
        ActionHeader closeSequenceActionHeader;
        ActionHeader closeSequenceResponseActionHeader; 
        ActionHeader createSequenceActionHeader; 
        ActionHeader sequenceAcknowledgementActionHeader;
        ActionHeader terminateSequenceActionHeader; 
        ActionHeader terminateSequenceResponseActionHeader;

        internal Wsrm11Index(AddressingVersion addressingVersion)
        { 
            this.addressingVersion = addressingVersion;
        } 
 
        internal static MessagePartSpecification SignedReliabilityMessageParts
        { 
            get
            {
                if (signedReliabilityMessageParts == null)
                { 
                    XmlQualifiedName[] wsrmMessageHeaders = new XmlQualifiedName[]
                    { 
                        new XmlQualifiedName(WsrmFeb2005Strings.Sequence, Wsrm11Strings.Namespace), 
                        new XmlQualifiedName(WsrmFeb2005Strings.SequenceAcknowledgement, Wsrm11Strings.Namespace),
                        new XmlQualifiedName(WsrmFeb2005Strings.AckRequested, Wsrm11Strings.Namespace), 
                        new XmlQualifiedName(Wsrm11Strings.UsesSequenceSTR, Wsrm11Strings.Namespace),
                    };

                    MessagePartSpecification s = new MessagePartSpecification(wsrmMessageHeaders); 
                    s.MakeReadOnly();
                    signedReliabilityMessageParts = s; 
                } 

                return signedReliabilityMessageParts; 
            }
        }

        protected override ActionHeader GetActionHeader(string element) 
        {
            Wsrm11Dictionary wsrm11Dictionary = DXD.Wsrm11Dictionary; 
            if (element == WsrmFeb2005Strings.AckRequested) 
            {
                if (ackRequestedActionHeader == null) 
                {
                    ackRequestedActionHeader = ActionHeader.Create(wsrm11Dictionary.AckRequestedAction,
                        this.addressingVersion);
                } 

                return ackRequestedActionHeader; 
            } 
            else if (element == WsrmFeb2005Strings.CreateSequence)
            { 
                if (createSequenceActionHeader == null)
                {
                    createSequenceActionHeader = ActionHeader.Create(wsrm11Dictionary.CreateSequenceAction,
                        this.addressingVersion); 
                }
 
                return createSequenceActionHeader; 
            }
            else if (element == WsrmFeb2005Strings.SequenceAcknowledgement) 
            {
                if (sequenceAcknowledgementActionHeader == null)
                {
                    sequenceAcknowledgementActionHeader = 
                        ActionHeader.Create(wsrm11Dictionary.SequenceAcknowledgementAction,
                        this.addressingVersion); 
                } 

                return sequenceAcknowledgementActionHeader; 
            }
            else if (element == WsrmFeb2005Strings.TerminateSequence)
            {
                if (terminateSequenceActionHeader == null) 
                {
                    terminateSequenceActionHeader = 
                        ActionHeader.Create(wsrm11Dictionary.TerminateSequenceAction, this.addressingVersion); 
                }
 
                return terminateSequenceActionHeader;
            }
            else if (element == Wsrm11Strings.TerminateSequenceResponse)
            { 
                if (terminateSequenceResponseActionHeader == null)
                { 
                    terminateSequenceResponseActionHeader = 
                        ActionHeader.Create(wsrm11Dictionary.TerminateSequenceResponseAction, this.addressingVersion);
                } 

                return terminateSequenceResponseActionHeader;
            }
            else if (element == Wsrm11Strings.CloseSequence) 
            {
                if (closeSequenceActionHeader == null) 
                { 
                    closeSequenceActionHeader =
                        ActionHeader.Create(wsrm11Dictionary.CloseSequenceAction, this.addressingVersion); 
                }

                return closeSequenceActionHeader;
            } 
            else if (element == Wsrm11Strings.CloseSequenceResponse)
            { 
                if (closeSequenceResponseActionHeader == null) 
                {
                    closeSequenceResponseActionHeader = 
                        ActionHeader.Create(wsrm11Dictionary.CloseSequenceResponseAction, this.addressingVersion);
                }

                return closeSequenceResponseActionHeader; 
            }
            else 
            { 
                DiagnosticUtility.DebugAssert("Element not supported.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            }
        }
    }
 
    class WsrmFeb2005Index : WsrmIndex
    { 
        static MessagePartSpecification signedReliabilityMessageParts; 

        ActionHeader ackRequestedActionHeader; 
        AddressingVersion addressingVersion;
        ActionHeader createSequenceActionHeader;
        ActionHeader sequenceAcknowledgementActionHeader;
        ActionHeader terminateSequenceActionHeader; 

        internal WsrmFeb2005Index(AddressingVersion addressingVersion) 
        { 
            this.addressingVersion = addressingVersion;
        } 

        internal static MessagePartSpecification SignedReliabilityMessageParts
        {
            get 
            {
                if (signedReliabilityMessageParts == null) 
                { 
                    XmlQualifiedName[] wsrmMessageHeaders = new XmlQualifiedName[]
                    { 
                        new XmlQualifiedName(WsrmFeb2005Strings.Sequence, WsrmFeb2005Strings.Namespace),
                        new XmlQualifiedName(WsrmFeb2005Strings.SequenceAcknowledgement, WsrmFeb2005Strings.Namespace),
                        new XmlQualifiedName(WsrmFeb2005Strings.AckRequested, WsrmFeb2005Strings.Namespace),
                    }; 

                    MessagePartSpecification s = new MessagePartSpecification(wsrmMessageHeaders); 
                    s.MakeReadOnly(); 
                    signedReliabilityMessageParts = s;
                } 

                return signedReliabilityMessageParts;
            }
        } 

        protected override ActionHeader GetActionHeader(string element) 
        { 
            WsrmFeb2005Dictionary wsrmFeb2005Dictionary = XD.WsrmFeb2005Dictionary;
 
            if (element == WsrmFeb2005Strings.AckRequested)
            {
                if (ackRequestedActionHeader == null)
                { 
                    ackRequestedActionHeader = ActionHeader.Create(wsrmFeb2005Dictionary.AckRequestedAction,
                        this.addressingVersion); 
                } 

                return ackRequestedActionHeader; 
            }
            else if (element == WsrmFeb2005Strings.CreateSequence)
            {
                if (createSequenceActionHeader == null) 
                {
                    createSequenceActionHeader = 
                        ActionHeader.Create(wsrmFeb2005Dictionary.CreateSequenceAction, this.addressingVersion); 
                }
 
                return createSequenceActionHeader;
            }
            else if (element == WsrmFeb2005Strings.SequenceAcknowledgement)
            { 
                if (sequenceAcknowledgementActionHeader == null)
                { 
                    sequenceAcknowledgementActionHeader = 
                        ActionHeader.Create(wsrmFeb2005Dictionary.SequenceAcknowledgementAction,
                        this.addressingVersion); 
                }

                return sequenceAcknowledgementActionHeader;
            } 
            else if (element == WsrmFeb2005Strings.TerminateSequence)
            { 
                if (terminateSequenceActionHeader == null) 
                {
                    terminateSequenceActionHeader = 
                        ActionHeader.Create(wsrmFeb2005Dictionary.TerminateSequenceAction, this.addressingVersion);
                }

                return terminateSequenceActionHeader; 
            }
            else 
            { 
                DiagnosticUtility.DebugAssert("Element not supported.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            }
        }
    }
 
    static class WsrmUtilities
    { 
        public static TimeSpan CalculateKeepAliveInterval(TimeSpan inactivityTimeout, int maxRetryCount) 
        {
            return Ticks.ToTimeSpan(Ticks.FromTimeSpan(inactivityTimeout) / 2 / maxRetryCount); 
        }

        internal static UniqueId NextSequenceId()
        { 
            return new UniqueId();
        } 
 
        internal static void AddAcknowledgementHeader(ReliableMessagingVersion reliableMessagingVersion,
            Message message, UniqueId id, SequenceRangeCollection ranges, bool final) 
        {
            WsrmUtilities.AddAcknowledgementHeader(reliableMessagingVersion, message, id, ranges, final, -1);
        }
 
        internal static void AddAcknowledgementHeader(ReliableMessagingVersion reliableMessagingVersion,
            Message message, UniqueId id, SequenceRangeCollection ranges, bool final, int bufferRemaining) 
        { 
            message.Headers.Insert(0,
                new WsrmAcknowledgmentHeader(reliableMessagingVersion, id, ranges, final, bufferRemaining)); 
        }

        internal static void AddAckRequestedHeader(ReliableMessagingVersion reliableMessagingVersion, Message message,
            UniqueId id) 
        {
            message.Headers.Insert(0, new WsrmAckRequestedHeader(reliableMessagingVersion, id)); 
        } 

        internal static void AddSequenceHeader(ReliableMessagingVersion reliableMessagingVersion, Message message, 
            UniqueId id, Int64 sequenceNumber, bool isLast)
        {
            message.Headers.Insert(0,
                new WsrmSequencedMessageHeader(reliableMessagingVersion, id, sequenceNumber, isLast)); 
        }
 
        internal static void AssertWsrm11(ReliableMessagingVersion reliableMessagingVersion) 
        {
            if (reliableMessagingVersion != ReliableMessagingVersion.WSReliableMessaging11) 
            {
                DiagnosticUtility.DebugAssert("WS-ReliableMessaging 1.1 required.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            } 
        }
 
        internal static Message CreateAcknowledgmentMessage(MessageVersion version, 
            ReliableMessagingVersion reliableMessagingVersion, UniqueId id, SequenceRangeCollection ranges, bool final,
            int bufferRemaining) 
        {
            Message message = Message.CreateMessage(version,
                WsrmIndex.GetSequenceAcknowledgementActionHeader(version.Addressing, reliableMessagingVersion));
 
            WsrmUtilities.AddAcknowledgementHeader(reliableMessagingVersion, message, id, ranges, final,
                bufferRemaining); 
            message.Properties.AllowOutputBatching = false; 

            return message; 
        }

        internal static Message CreateAckRequestedMessage(MessageVersion messageVersion,
            ReliableMessagingVersion reliableMessagingVersion, UniqueId id) 
        {
            Message message = Message.CreateMessage(messageVersion, 
                WsrmIndex.GetAckRequestedActionHeader(messageVersion.Addressing, reliableMessagingVersion)); 

            WsrmUtilities.AddAckRequestedHeader(reliableMessagingVersion, message, id); 
            message.Properties.AllowOutputBatching = false;

            return message;
        } 

        internal static Message CreateCloseSequenceResponse(MessageVersion messageVersion, UniqueId messageId, 
            UniqueId inputId) 
        {
            CloseSequenceResponse response = new CloseSequenceResponse(inputId); 

            Message message = Message.CreateMessage(messageVersion,
                WsrmIndex.GetCloseSequenceResponseActionHeader(messageVersion.Addressing), response);
 
            message.Headers.RelatesTo = messageId;
            return message; 
        } 

        internal static Message CreateCreateSequenceResponse(MessageVersion messageVersion, 
            ReliableMessagingVersion reliableMessagingVersion, bool duplex, CreateSequenceInfo createSequenceInfo,
            bool ordered, UniqueId inputId, EndpointAddress acceptAcksTo)
        {
            CreateSequenceResponse response = new CreateSequenceResponse(messageVersion.Addressing, reliableMessagingVersion); 
            response.Identifier = inputId;
            response.Expires = createSequenceInfo.Expires; 
            response.Ordered = ordered; 

            if (duplex) 
                response.AcceptAcksTo = acceptAcksTo;

            Message responseMessage
                = Message.CreateMessage(messageVersion, ActionHeader.Create( 
                WsrmIndex.GetCreateSequenceResponseAction(reliableMessagingVersion), messageVersion.Addressing), response);
 
            return responseMessage; 
        }
 
        internal static Message CreateCSRefusedCommunicationFault(MessageVersion messageVersion,
            ReliableMessagingVersion reliableMessagingVersion, string reason)
        {
            return CreateCSRefusedFault(messageVersion, reliableMessagingVersion, false, null, reason); 
        }
 
        internal static Message CreateCSRefusedProtocolFault(MessageVersion messageVersion, 
            ReliableMessagingVersion reliableMessagingVersion, string reason)
        { 
            return CreateCSRefusedFault(messageVersion, reliableMessagingVersion, true, null, reason);
        }

        internal static Message CreateCSRefusedServerTooBusyFault(MessageVersion messageVersion, 
            ReliableMessagingVersion reliableMessagingVersion, string reason)
        { 
            FaultCode subCode = new FaultCode(WsrmFeb2005Strings.ConnectionLimitReached, 
                WsrmFeb2005Strings.NETNamespace);
            subCode = new FaultCode(WsrmFeb2005Strings.CreateSequenceRefused, 
                WsrmIndex.GetNamespaceString(reliableMessagingVersion), subCode);
            return CreateCSRefusedFault(messageVersion, reliableMessagingVersion, false, subCode, reason);
        }
 
        static Message CreateCSRefusedFault(MessageVersion messageVersion,
            ReliableMessagingVersion reliableMessagingVersion, bool isSenderFault, FaultCode subCode, string reason) 
        { 
            FaultCode code;
 
            if (messageVersion.Envelope == EnvelopeVersion.Soap11)
            {
                code = new FaultCode(WsrmFeb2005Strings.CreateSequenceRefused, WsrmIndex.GetNamespaceString(reliableMessagingVersion));
            } 
            else if (messageVersion.Envelope == EnvelopeVersion.Soap12)
            { 
                if (subCode == null) 
                    subCode = new FaultCode(WsrmFeb2005Strings.CreateSequenceRefused, WsrmIndex.GetNamespaceString(reliableMessagingVersion), subCode);
 
                if (isSenderFault)
                    code = FaultCode.CreateSenderFaultCode(subCode);
                else
                    code = FaultCode.CreateReceiverFaultCode(subCode); 
            }
            else 
            { 
                DiagnosticUtility.DebugAssert("Unsupported version.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            }

            FaultReason faultReason = new FaultReason(SR.GetString(SR.CSRefused, reason), CultureInfo.CurrentCulture);
 
            MessageFault fault = MessageFault.CreateFault(code, faultReason);
            string action = WsrmIndex.GetFaultActionString(messageVersion.Addressing, reliableMessagingVersion); 
            return Message.CreateMessage(messageVersion, fault, action); 
        }
 
        public static Exception CreateCSFaultException(MessageVersion version,
            ReliableMessagingVersion reliableMessagingVersion, Message message, IChannel innerChannel)
        {
            MessageFault fault = MessageFault.CreateFault(message, TransportDefaults.MaxRMFaultSize); 
            FaultCode code = fault.Code;
            FaultCode subCode; 
 
            if (version.Envelope == EnvelopeVersion.Soap11)
            { 
                subCode = code;
            }
            else if (version.Envelope == EnvelopeVersion.Soap12)
            { 
                subCode = code.SubCode;
            } 
            else 
            {
                DiagnosticUtility.DebugAssert("Unsupported version."); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            }

            if (subCode != null) 
            {
                // CreateSequenceRefused 
                if ((subCode.Namespace == WsrmIndex.GetNamespaceString(reliableMessagingVersion)) 
                    && (subCode.Name == WsrmFeb2005Strings.CreateSequenceRefused))
                { 
                    string reason = FaultException.GetSafeReasonText(fault);

                    if (version.Envelope == EnvelopeVersion.Soap12)
                    { 
                        FaultCode subSubCode = subCode.SubCode;
                        if ((subSubCode != null) 
                            && (subSubCode.Namespace == WsrmFeb2005Strings.NETNamespace) 
                            && (subSubCode.Name == WsrmFeb2005Strings.ConnectionLimitReached))
                        { 
                            return new ServerTooBusyException(reason);
                        }

                        if (code.IsSenderFault) 
                        {
                            return new ProtocolException(reason); 
                        } 
                    }
 
                    return new CommunicationException(reason);
                }
                else if ((subCode.Namespace == version.Addressing.Namespace)
                    && (subCode.Name == AddressingStrings.EndpointUnavailable)) 
                {
                    return new EndpointNotFoundException(FaultException.GetSafeReasonText(fault)); 
                } 
            }
 
            FaultConverter faultConverter = innerChannel.GetProperty();
            if (faultConverter == null)
                faultConverter = FaultConverter.GetDefaultFaultConverter(version);
 
            Exception exception;
            if (faultConverter.TryCreateException(message, fault, out exception)) 
            { 
                return exception;
            } 
            else
            {
                return new ProtocolException(SR.GetString(SR.UnrecognizedFaultReceivedOnOpen, fault.Code.Namespace, fault.Code.Name, FaultException.GetSafeReasonText(fault)));
            } 
        }
 
        internal static Message CreateEndpointNotFoundFault(MessageVersion version, string reason) 
        {
            FaultCode subCode = new FaultCode(AddressingStrings.EndpointUnavailable, version.Addressing.Namespace); 
            FaultCode code;

            if (version.Envelope == EnvelopeVersion.Soap11)
            { 
                code = subCode;
            } 
            else if (version.Envelope == EnvelopeVersion.Soap12) 
            {
                code = FaultCode.CreateSenderFaultCode(subCode); 
            }
            else
            {
                DiagnosticUtility.DebugAssert("Unsupported version."); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            } 
 
            FaultReason faultReason = new FaultReason(reason, CultureInfo.CurrentCulture);
            MessageFault fault = MessageFault.CreateFault(code, faultReason); 
            return Message.CreateMessage(version, fault, version.Addressing.DefaultFaultAction);
        }

        internal static Message CreateTerminateMessage(MessageVersion version, 
            ReliableMessagingVersion reliableMessagingVersion, UniqueId id)
        { 
            return CreateTerminateMessage(version, reliableMessagingVersion, id, -1); 
        }
 
        internal static Message CreateTerminateMessage(MessageVersion version,
            ReliableMessagingVersion reliableMessagingVersion, UniqueId id, Int64 last)
        {
            Message message = Message.CreateMessage(version, 
                WsrmIndex.GetTerminateSequenceActionHeader(version.Addressing, reliableMessagingVersion),
                new TerminateSequence(reliableMessagingVersion, id, last)); 
 
            message.Properties.AllowOutputBatching = false;
 
            return message;
        }

        internal static Message CreateTerminateResponseMessage(MessageVersion version, UniqueId messageId, UniqueId sequenceId) 
        {
            Message message = Message.CreateMessage(version, 
                WsrmIndex.GetTerminateSequenceResponseActionHeader(version.Addressing), 
                new TerminateSequenceResponse(sequenceId));
 
            message.Properties.AllowOutputBatching = false;
            message.Headers.RelatesTo = messageId;
            return message;
        } 

        internal static UniqueId GetInputId(WsrmMessageInfo info) 
        { 
            if (info.TerminateSequenceInfo != null)
            { 
                return info.TerminateSequenceInfo.Identifier;
            }

            if (info.SequencedMessageInfo != null) 
            {
                return info.SequencedMessageInfo.SequenceID; 
            } 

            if (info.AckRequestedInfo != null) 
            {
                return info.AckRequestedInfo.SequenceID;
            }
 
            if (info.WsrmHeaderFault != null && info.WsrmHeaderFault.FaultsInput)
            { 
                return info.WsrmHeaderFault.SequenceID; 
            }
 
            if (info.CloseSequenceInfo != null)
            {
                return info.CloseSequenceInfo.Identifier;
            } 

            return null; 
        } 

        internal static UniqueId GetOutputId(ReliableMessagingVersion reliableMessagingVersion, WsrmMessageInfo info) 
        {
            if (info.AcknowledgementInfo != null)
            {
                return info.AcknowledgementInfo.SequenceID; 
            }
 
            if (info.WsrmHeaderFault != null && info.WsrmHeaderFault.FaultsOutput) 
            {
                return info.WsrmHeaderFault.SequenceID; 
            }

            if (info.TerminateSequenceResponseInfo != null)
            { 
                return info.TerminateSequenceResponseInfo.Identifier;
            } 
 
            if (reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
            { 
                if (info.CloseSequenceInfo != null)
                {
                    return info.CloseSequenceInfo.Identifier;
                } 

                if (info.CloseSequenceResponseInfo != null) 
                { 
                    return info.CloseSequenceResponseInfo.Identifier;
                } 

                if (info.TerminateSequenceResponseInfo != null)
                {
                    return info.TerminateSequenceResponseInfo.Identifier; 
                }
            } 
 
            return null;
        } 

        internal static bool IsWsrmAction(ReliableMessagingVersion reliableMessagingVersion, string action)
        {
            if (action == null) 
                return false;
            return (action.StartsWith(WsrmIndex.GetNamespaceString(reliableMessagingVersion), StringComparison.Ordinal)); 
        } 

        public static void ReadEmptyElement(XmlDictionaryReader reader) 
        {
            if (reader.IsEmptyElement)
            {
                reader.Read(); 
            }
            else 
            { 
                reader.Read();
                reader.ReadEndElement(); 
            }
        }

        public static UniqueId ReadIdentifier(XmlDictionaryReader reader, 
            ReliableMessagingVersion reliableMessagingVersion)
        { 
            reader.ReadStartElement(XD.WsrmFeb2005Dictionary.Identifier, WsrmIndex.GetNamespace(reliableMessagingVersion)); 
            UniqueId sequenceID = reader.ReadContentAsUniqueId();
            reader.ReadEndElement(); 
            return sequenceID;
        }

        public static Int64 ReadSequenceNumber(XmlDictionaryReader reader) 
        {
            return WsrmUtilities.ReadSequenceNumber(reader, false); 
        } 

        public static Int64 ReadSequenceNumber(XmlDictionaryReader reader, bool allowZero) 
        {
            Int64 sequenceNumber = reader.ReadContentAsLong();

            if (sequenceNumber < 0 || (sequenceNumber == 0 && !allowZero)) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException( 
                    SR.GetString(SR.InvalidSequenceNumber, sequenceNumber))); 
            }
 
            return sequenceNumber;
        }

        // Caller owns message. 
        public static WsrmFault ValidateCloseSequenceResponse(ChannelReliableSession session, UniqueId messageId,
            WsrmMessageInfo info, Int64 last) 
        { 
            string exceptionString = null;
            string faultString = null; 

            if (info.CloseSequenceResponseInfo == null)
            {
                exceptionString = SR.GetString(SR.InvalidWsrmResponseSessionFaultedExceptionString, 
                    Wsrm11Strings.CloseSequence, info.Action,
                    Wsrm11Strings.CloseSequenceResponseAction); 
                faultString = SR.GetString(SR.InvalidWsrmResponseSessionFaultedFaultString, 
                    Wsrm11Strings.CloseSequence, info.Action,
                    Wsrm11Strings.CloseSequenceResponseAction); 
            }
            else if (!object.Equals(messageId, info.CloseSequenceResponseInfo.RelatesTo))
            {
                exceptionString = SR.GetString(SR.WsrmMessageWithWrongRelatesToExceptionString, Wsrm11Strings.CloseSequence); 
                faultString = SR.GetString(SR.WsrmMessageWithWrongRelatesToFaultString, Wsrm11Strings.CloseSequence);
            } 
            else if (info.AcknowledgementInfo == null || !info.AcknowledgementInfo.Final) 
            {
                exceptionString = SR.GetString(SR.MissingFinalAckExceptionString); 
                faultString = SR.GetString(SR.SequenceTerminatedMissingFinalAck);
            }
            else
            { 
                return ValidateFinalAck(session, info, last);
            } 
 
            UniqueId sequenceId = session.OutputID;
            return SequenceTerminatedFault.CreateProtocolFault(sequenceId, faultString, exceptionString); 
        }

        public static bool ValidateCreateSequence(WsrmMessageInfo info,
            ReliableChannelListenerBase listener, IChannel channel, out EndpointAddress acksTo) 
            where TChannel : class, IChannel
        { 
            acksTo = null; 
            string reason = null;
 
            if (info.CreateSequenceInfo.OfferIdentifier == null)
            {
                if (typeof(TChannel) == typeof(IDuplexSessionChannel))
                    reason = SR.GetString(SR.CSRefusedDuplexNoOffer, listener.Uri); 
                else if (typeof(TChannel) == typeof(IReplySessionChannel))
                    reason = SR.GetString(SR.CSRefusedReplyNoOffer, listener.Uri); 
            } 
            else if (listener.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
            { 
                if (typeof(TChannel) == typeof(IInputSessionChannel))
                    reason = SR.GetString(SR.CSRefusedInputOffer, listener.Uri);
            }
 
            if (reason != null)
            { 
                info.FaultReply = WsrmUtilities.CreateCSRefusedProtocolFault(listener.MessageVersion, 
                    listener.ReliableMessagingVersion, reason);
                info.FaultException = new ProtocolException(SR.GetString(SR.ConflictingOffer)); 
                return false;
            }

            if (listener.LocalAddresses != null) 
            {
                Collection addresses = new Collection(); 
 
                try
                { 
                    listener.LocalAddresses.GetMatchingValues(info.Message, addresses);
                }
                catch (CommunicationException e)
                { 
                    FaultConverter converter = channel.GetProperty();
                    if (converter == null) 
                        converter = FaultConverter.GetDefaultFaultConverter(listener.MessageVersion); 

                    Message faultReply; 
                    if (converter.TryCreateFaultMessage(e, out faultReply))
                    {
                        info.FaultReply = faultReply;
                        info.FaultException = new ProtocolException(SR.GetString(SR.MessageExceptionOccurred), e); 
                        return false;
                    } 
 
                    throw;
                } 

                if (addresses.Count > 0)
                {
                    EndpointAddress match = addresses[0]; 
                    acksTo = new EndpointAddress(info.CreateSequenceInfo.To, match.Identity, match.Headers);
                    return true; 
                } 
                else
                { 
                    info.FaultReply = CreateEndpointNotFoundFault(listener.MessageVersion, SR.GetString(SR.EndpointNotFound, info.CreateSequenceInfo.To));
                    info.FaultException = new ProtocolException(SR.GetString(SR.ConflictingAddress));
                    return false;
                } 
            }
            else 
            { 
                acksTo = new EndpointAddress(info.CreateSequenceInfo.To);
                return true; 
            }
        }

        public static WsrmFault ValidateFinalAck(ChannelReliableSession session, WsrmMessageInfo info, Int64 last) 
        {
            WsrmAcknowledgmentInfo ackInfo = info.AcknowledgementInfo; 
            WsrmFault fault = ValidateFinalAckExists(session, ackInfo); 

            if (fault != null) 
            {
                return fault;
            }
 
            SequenceRangeCollection finalRanges = ackInfo.Ranges;
 
            if (last == 0) 
            {
                if (finalRanges.Count == 0) 
                {
                    return null;
                }
            } 
            else
            { 
                if ((finalRanges.Count == 1) && (finalRanges[0].Lower == 1) && (finalRanges[0].Upper == last)) 
                {
                    return null; 
                }
            }

            return new InvalidAcknowledgementFault(session.OutputID, ackInfo.Ranges); 
        }
 
        public static WsrmFault ValidateFinalAckExists(ChannelReliableSession session, WsrmAcknowledgmentInfo ackInfo) 
        {
            if (ackInfo == null || !ackInfo.Final) 
            {
                string exceptionString = SR.GetString(SR.MissingFinalAckExceptionString);
                string faultString = SR.GetString(SR.SequenceTerminatedMissingFinalAck);
                return SequenceTerminatedFault.CreateProtocolFault(session.OutputID, faultString, exceptionString); 
            }
 
            return null; 
        }
 
        // Caller owns message.
        public static WsrmFault ValidateTerminateSequenceResponse(ChannelReliableSession session, UniqueId messageId,
            WsrmMessageInfo info, Int64 last)
        { 
            string exceptionString = null;
            string faultString = null; 
 
            if (info.WsrmHeaderFault is UnknownSequenceFault)
            { 
                return null;
            }
            else if (info.TerminateSequenceResponseInfo == null)
            { 
                exceptionString = SR.GetString(SR.InvalidWsrmResponseSessionFaultedExceptionString,
                    WsrmFeb2005Strings.TerminateSequence, info.Action, 
                    Wsrm11Strings.TerminateSequenceResponseAction); 
                faultString = SR.GetString(SR.InvalidWsrmResponseSessionFaultedFaultString,
                    WsrmFeb2005Strings.TerminateSequence, info.Action, 
                    Wsrm11Strings.TerminateSequenceResponseAction);
            }
            else if (!object.Equals(messageId, info.TerminateSequenceResponseInfo.RelatesTo))
            { 
                exceptionString = SR.GetString(SR.WsrmMessageWithWrongRelatesToExceptionString, WsrmFeb2005Strings.TerminateSequence);
                faultString = SR.GetString(SR.WsrmMessageWithWrongRelatesToFaultString, WsrmFeb2005Strings.TerminateSequence); 
            } 
            else
            { 
                return ValidateFinalAck(session, info, last);
            }

            UniqueId sequenceId = session.OutputID; 
            return SequenceTerminatedFault.CreateProtocolFault(sequenceId, faultString, exceptionString);
        } 
 
        // Checks that ReplyTo and RemoteAddress are equivalent. Will fault the session with SequenceTerminatedFault.
        // Meant to be used for CloseSequence and TerminateSequence in Wsrm 1.1. 
        public static bool ValidateWsrmRequest(ChannelReliableSession session, WsrmRequestInfo info,
            IReliableChannelBinder binder, RequestContext context)
        {
            if (!(info is CloseSequenceInfo) && !(info is TerminateSequenceInfo)) 
            {
                DiagnosticUtility.DebugAssert("Method is meant for CloseSequence or TerminateSequence only."); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            }
 
            if (info.ReplyTo.Uri != binder.RemoteAddress.Uri)
            {
                string faultString = SR.GetString(SR.WsrmRequestIncorrectReplyToFaultString, info.RequestName);
                string exceptionString = SR.GetString(SR.WsrmRequestIncorrectReplyToExceptionString, info.RequestName); 
                WsrmFault fault = SequenceTerminatedFault.CreateProtocolFault(session.InputID, faultString, exceptionString);
                session.OnLocalFault(fault.CreateException(), fault, context); 
                return false; 
            }
            else 
            {
                return true;
            }
        } 

        public static void WriteIdentifier(XmlDictionaryWriter writer, 
            ReliableMessagingVersion reliableMessagingVersion, UniqueId sequenceId) 
        {
            writer.WriteStartElement(WsrmFeb2005Strings.Prefix, XD.WsrmFeb2005Dictionary.Identifier, 
                WsrmIndex.GetNamespace(reliableMessagingVersion));
            writer.WriteValue(sequenceId);
            writer.WriteEndElement();
        } 

        // These are strings that are not actually used anywhere. 
        // This method and resources strings can be deleted whenever the resource file can be changed. 
        public static string UseStrings()
        { 
            string s = SR.SupportedAddressingModeNotSupported;
            s = SR.SequenceTerminatedUnexpectedCloseSequence;
            s = SR.UnexpectedCloseSequence;
            s = SR.SequenceTerminatedUnsupportedTerminateSequence; 
            return s;
        } 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK