File: System\ServiceModel\Dispatcher\ErrorHandlingAcceptor.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
 
namespace System.ServiceModel.Dispatcher
{
    using System;
    using System.Runtime;
    using System.ServiceModel;
 
    class ErrorHandlingAcceptor
    {
        readonly ChannelDispatcher dispatcher;
        readonly IListenerBinder binder;
 
        internal ErrorHandlingAcceptor(IListenerBinder binder, ChannelDispatcher dispatcher)
        {
            if (binder == null)
            {
                Fx.Assert("binder is null");
            }
            if (dispatcher == null)
            {
                Fx.Assert("dispatcher is null");
            }
 
            this.binder = binder;
            this.dispatcher = dispatcher;
        }
 
        internal void Close()
        {
            try
            {
                this.binder.Listener.Close();
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
                this.HandleError(e);
            }
        }
 
        void HandleError(Exception e)
        {
            if (this.dispatcher != null)
            {
                this.dispatcher.HandleError(e);
            }
        }
 
        void HandleErrorOrAbort(Exception e)
        {
            if ((this.dispatcher == null) || !this.dispatcher.HandleError(e))
            {
                // We only stop if the listener faults.  It is a bug
                // if the listener is in an invalid state and does not
                // fault.  So there are no cases today where this aborts.
            }
        }
 
        internal bool TryAccept(TimeSpan timeout, out IChannelBinder channelBinder)
        {
            try
            {
                channelBinder = this.binder.Accept(timeout);
                if (channelBinder != null)
                {
                    this.dispatcher.PendingChannels.Add(channelBinder.Channel);
                }
                return true;
            }
            catch (CommunicationObjectAbortedException)
            {
                channelBinder = null;
                return true;
            }
            catch (CommunicationObjectFaultedException)
            {
                channelBinder = null;
                return true;
            }
            catch (TimeoutException)
            {
                channelBinder = null;
                return false;
            }
            catch (CommunicationException e)
            {
                this.HandleError(e);
                channelBinder = null;
                return false;
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
                this.HandleErrorOrAbort(e);
                channelBinder = null;
                return false;
            }
        }
 
        internal IAsyncResult BeginTryAccept(TimeSpan timeout, AsyncCallback callback, object state)
        {
            try
            {
                return this.binder.BeginAccept(timeout, callback, state);
            }
            catch (CommunicationObjectAbortedException)
            {
                return new ErrorHandlingCompletedAsyncResult(true, callback, state);
            }
            catch (CommunicationObjectFaultedException)
            {
                return new ErrorHandlingCompletedAsyncResult(true, callback, state);
            }
            catch (TimeoutException)
            {
                return new ErrorHandlingCompletedAsyncResult(false, callback, state);
            }
            catch (CommunicationException e)
            {
                this.HandleError(e);
                return new ErrorHandlingCompletedAsyncResult(false, callback, state);
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
                this.HandleErrorOrAbort(e);
                return new ErrorHandlingCompletedAsyncResult(false, callback, state);
            }
        }
 
        internal bool EndTryAccept(IAsyncResult result, out IChannelBinder channelBinder)
        {
            ErrorHandlingCompletedAsyncResult handlerResult = result as ErrorHandlingCompletedAsyncResult;
            if (handlerResult != null)
            {
                channelBinder = null;
                return ErrorHandlingCompletedAsyncResult.End(handlerResult);
            }
            else
            {
                try
                {
                    channelBinder = this.binder.EndAccept(result);
                    if (channelBinder != null)
                    {
                        this.dispatcher.PendingChannels.Add(channelBinder.Channel);
                    }
                    return true;
                }
                catch (CommunicationObjectAbortedException)
                {
                    channelBinder = null;
                    return true;
                }
                catch (CommunicationObjectFaultedException)
                {
                    channelBinder = null;
                    return true;
                }
                catch (TimeoutException)
                {
                    channelBinder = null;
                    return false;
                }
                catch (CommunicationException e)
                {
                    this.HandleError(e);
                    channelBinder = null;
                    return false;
                }
                catch (Exception e)
                {
                    if (Fx.IsFatal(e))
                    {
                        throw;
                    }
                    this.HandleErrorOrAbort(e);
                    channelBinder = null;
                    return false;
                }
            }
        }
 
        internal void WaitForChannel()
        {
            try
            {
                this.binder.Listener.WaitForChannel(TimeSpan.MaxValue);
            }
            catch (CommunicationObjectAbortedException) { }
            catch (CommunicationObjectFaultedException) { }
            catch (CommunicationException e)
            {
                this.HandleError(e);
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
                this.HandleErrorOrAbort(e);
            }
        }
 
        internal IAsyncResult BeginWaitForChannel(AsyncCallback callback, object state)
        {
            try
            {
                return this.binder.Listener.BeginWaitForChannel(TimeSpan.MaxValue, callback, state);
            }
            catch (CommunicationObjectAbortedException)
            {
                return new WaitCompletedAsyncResult(callback, state);
            }
            catch (CommunicationObjectFaultedException)
            {
                return new WaitCompletedAsyncResult(callback, state);
            }
            catch (CommunicationException e)
            {
                this.HandleError(e);
                return new WaitCompletedAsyncResult(callback, state);
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
                this.HandleErrorOrAbort(e);
                return new WaitCompletedAsyncResult(callback, state);
            }
        }
 
        internal void EndWaitForChannel(IAsyncResult result)
        {
            WaitCompletedAsyncResult handlerResult = result as WaitCompletedAsyncResult;
            if (handlerResult != null)
            {
                WaitCompletedAsyncResult.End(handlerResult);
            }
            else
            {
                try
                {
                    this.binder.Listener.EndWaitForChannel(result);
                }
                catch (CommunicationObjectAbortedException) { }
                catch (CommunicationObjectFaultedException) { }
                catch (CommunicationException e)
                {
                    this.HandleError(e);
                }
                catch (Exception e)
                {
                    if (Fx.IsFatal(e))
                    {
                        throw;
                    }
                    this.HandleErrorOrAbort(e);
                }
            }
        }
 
        class ErrorHandlingCompletedAsyncResult : CompletedAsyncResult<bool>
        {
            internal ErrorHandlingCompletedAsyncResult(bool data, AsyncCallback callback, object state)
                : base(data, callback, state)
            {
            }
        }
 
        class WaitCompletedAsyncResult : CompletedAsyncResult
        {
            internal WaitCompletedAsyncResult(AsyncCallback callback, object state)
                : base(callback, state)
            {
            }
        }
    }
}