ListenerHandler.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 / Dispatcher / ListenerHandler.cs / 1 / ListenerHandler.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------

namespace System.ServiceModel.Dispatcher 
{
    using System; 
    using System.ServiceModel; 
    using System.Collections.Generic;
    using System.Diagnostics; 
    using System.Runtime.CompilerServices;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Diagnostics;
    using System.Threading; 
    using System.Transactions;
    using SessionIdleManager = System.ServiceModel.Channels.ServiceChannel.SessionIdleManager; 
 
    class ListenerHandler : CommunicationObject, ISessionThrottleNotification
    { 
        static AsyncCallback acceptCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(ListenerHandler.AcceptCallback));
        static WaitCallback initiateChannelPump = new WaitCallback(ListenerHandler.InitiateChannelPump);

        readonly ErrorHandlingAcceptor acceptor; 
        readonly ChannelDispatcher channelDispatcher;
        ListenerChannel channel; 
        SessionIdleManager idleManager; 
        bool acceptedNull;
        bool doneAccepting; 
        EndpointDispatcherTable endpoints;
        readonly ServiceHostBase host;
        readonly IListenerBinder listenerBinder;
        readonly ServiceThrottle throttle; 
        IDefaultCommunicationTimeouts timeouts;
        static TimeSpan transactionalTimeout { get { return TimeSpan.FromSeconds(5); } } 
        WrappedTransaction wrappedTransaction; 

        internal ListenerHandler(IListenerBinder listenerBinder, ChannelDispatcher channelDispatcher, ServiceHostBase host, ServiceThrottle throttle, IDefaultCommunicationTimeouts timeouts) 
        {
            this.listenerBinder = listenerBinder;
            if (!((this.listenerBinder != null)))
            { 
                DiagnosticUtility.DebugAssert("ListenerHandler.ctor: (this.listenerBinder != null)");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("listenerBinder"); 
            } 

            this.channelDispatcher = channelDispatcher; 
            if (!((this.channelDispatcher != null)))
            {
                DiagnosticUtility.DebugAssert("ListenerHandler.ctor: (this.channelDispatcher != null)");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("channelDispatcher"); 
            }
 
            this.host = host; 
            if (!((this.host != null)))
            { 
                DiagnosticUtility.DebugAssert("ListenerHandler.ctor: (this.host != null)");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("host");
            }
 
            this.throttle = throttle;
            if (!((this.throttle != null))) 
            { 
                DiagnosticUtility.DebugAssert("ListenerHandler.ctor: (this.throttle != null)");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("throttle"); 
            }

            this.timeouts = timeouts;
 
            this.endpoints = channelDispatcher.EndpointDispatcherTable;
            this.acceptor = new ErrorHandlingAcceptor(listenerBinder, channelDispatcher); 
        } 

        internal ChannelDispatcher ChannelDispatcher 
        {
            get { return this.channelDispatcher; }
        }
 
        internal ListenerChannel Channel
        { 
            get { return this.channel; } 
        }
 
        protected override TimeSpan DefaultCloseTimeout
        {
            get { return this.host.CloseTimeout; }
        } 

        protected override TimeSpan DefaultOpenTimeout 
        { 
            get { return this.host.OpenTimeout; }
        } 

        internal EndpointDispatcherTable Endpoints
        {
            get { return this.endpoints; } 
            set { this.endpoints = value; }
        } 
 
        internal ServiceHostBase Host
        { 
            get { return this.host; }
        }

        new internal object ThisLock 
        {
            get { return base.ThisLock; } 
        } 

        protected override void OnOpen(TimeSpan timeout) 
        {
        }

        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) 
        {
            return new CompletedAsyncResult(callback, state); 
        } 

        protected override void OnEndOpen(IAsyncResult result) 
        {
            CompletedAsyncResult.End(result);
        }
 
        protected override void OnOpened()
        { 
            base.OnOpened(); 
            this.channelDispatcher.Channels.IncrementActivityCount();
            NewChannelPump(); 
        }

        internal void NewChannelPump()
        { 
            IOThreadScheduler.ScheduleCallback(ListenerHandler.initiateChannelPump, this);
        } 
 
        static void InitiateChannelPump(object state)
        { 
            ListenerHandler listenerHandler = state as ListenerHandler;

            if (listenerHandler.ChannelDispatcher.IsTransactedAccept)
            { 
                listenerHandler.TransactedChannelPump();
            } 
            else 
            {
                listenerHandler.ChannelPump(); 
            }
        }

        void ChannelPump() 
        {
            IChannelListener listener = this.listenerBinder.Listener; 
 
            for (;;)
            { 
                if (this.acceptedNull || (listener.State == CommunicationState.Faulted))
                {
                    this.DoneAccepting();
                    break; 
                }
 
                if (!this.Accept() || !this.AcquireThrottle()) 
                {
                    break; 
                }

                this.Dispatch();
            } 
        }
 
        [MethodImpl(MethodImplOptions.NoInlining)] 
        void TransactedChannelPump()
        { 
            IChannelListener listener = this.listenerBinder.Listener;

            for (;;)
            { 
                if (this.acceptedNull || (listener.State == CommunicationState.Faulted))
                { 
                    this.DoneAccepting(); 
                    break;
                } 

                this.acceptor.WaitForChannel();

                Transaction tx; 
                if (this.TransactedAccept(out tx))
                { 
                    if (null != tx) 
                    {
                        this.wrappedTransaction = new WrappedTransaction(tx); 

                        if (!this.AcquireThrottle())
                            break;
 
                        this.Dispatch();
                    } 
                } 
            }
        } 

        void AbortChannels()
        {
            IChannel[] channels = this.channelDispatcher.Channels.ToArray(); 
            for (int index = 0; index < channels.Length; index++)
            { 
                channels[index].Abort(); 
            }
        } 

        bool Accept()
        {
            IAsyncResult result = this.acceptor.BeginTryAccept(TimeSpan.MaxValue, ListenerHandler.acceptCallback, this); 
            return result.CompletedSynchronously && (this.channel != null);
        } 
 
        bool TransactedAccept(out Transaction tx)
        { 
            tx = null;

            try
            { 
                tx = TransactionBehavior.CreateTransaction(this.ChannelDispatcher.TransactionIsolationLevel, this.ChannelDispatcher.TransactionTimeout);
 
                IChannelBinder binder = null; 
                using (TransactionScope scope = new TransactionScope(tx))
                { 
                    if (!this.acceptor.TryAccept(transactionalTimeout, out binder))
                    {
                        return false;
                    } 
                    scope.Complete();
                } 
                if (null != binder) 
                {
                    this.channel = new ListenerChannel(binder); 
                    this.idleManager = SessionIdleManager.CreateIfNeeded(this.channel.Binder, this.channelDispatcher.DefaultCommunicationTimeouts.ReceiveTimeout);
                    return true;
                }
                else 
                {
                    this.AcceptedNull(); 
                    tx = null; 
                    return false;
                } 
            }
            catch (CommunicationException e)
            {
                if (null != tx) 
                {
                    try 
                    { 
                        tx.Rollback();
                    } 
                    catch (TransactionException ex)
                    {
                        if (DiagnosticUtility.ShouldTraceInformation)
                        { 
                            DiagnosticUtility.ExceptionUtility.TraceHandledException(ex, TraceEventType.Information);
                        } 
                    } 
                }
                tx = null; 

                if (DiagnosticUtility.ShouldTraceInformation)
                {
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                }
 
                return false; 
            }
            catch (TransactionException e) 
            {
                tx = null;

                if (DiagnosticUtility.ShouldTraceInformation) 
                {
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                } 

                return false; 
            }
        }

        ListenerChannel CompleteAccept(IAsyncResult result) 
        {
            IChannelBinder binder; 
            bool valid = this.acceptor.EndTryAccept(result, out binder); 

            if (valid) 
            {
                if (binder != null)
                {
                    return new ListenerChannel(binder); 
                }
                else 
                { 
                    this.AcceptedNull();
                    return null; 
                }
            }
            else
            { 
                return null;
            } 
        } 

        static void AcceptCallback(IAsyncResult result) 
        {
            ((ListenerHandler)result.AsyncState).AcceptReady(result);
        }
 
        void AcceptReady(IAsyncResult result)
        { 
            this.channel = this.CompleteAccept(result); 
            if (this.channel != null)
            { 
                DiagnosticUtility.DebugAssert(this.idleManager == null, "There cannot be an existing idle manager");
                this.idleManager = SessionIdleManager.CreateIfNeeded(this.channel.Binder, this.channelDispatcher.DefaultCommunicationTimeouts.ReceiveTimeout);
            }
            // If we didn't complete synchronously, this is a clean threadpool thread 
            bool cleanThread = !result.CompletedSynchronously;
 
            if (this.channel == null) 
            {
                this.DoneAccepting(); 
                return;
            }

            if (cleanThread && this.AcquireThrottle()) 
            {
                this.Dispatch(); 
                this.ChannelPump(); 
            }
        } 

        bool AcquireThrottle()
        {
            if ((this.channel != null) && (this.throttle != null) && (this.channelDispatcher.Session)) 
            {
                return this.throttle.AcquireSession(this); 
            } 

            return true; 
        }

        // This callback always occurs async and always on a dirty thread
        public void ThrottleAcquired() 
        {
            this.Dispatch(); 
            this.NewChannelPump(); 
        }
 
        void CloseChannel(IChannel channel, TimeSpan timeout)
        {
            try
            { 
                if (channel.State != CommunicationState.Closing && channel.State != CommunicationState.Closed)
                { 
                    CloseChannelState state = new CloseChannelState(this, channel); 
                    if (channel is ISessionChannel)
                    { 
                        IDuplexSession duplexSession = ((ISessionChannel)channel).Session;
                        IAsyncResult result = duplexSession.BeginCloseOutputSession(timeout, DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(CloseOutputSessionCallback)), state);
                        if (result.CompletedSynchronously)
                            duplexSession.EndCloseOutputSession(result); 
                    }
                    else 
                    { 
                        IAsyncResult result = channel.BeginClose(timeout, DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(CloseChannelCallback)), state);
                        if (result.CompletedSynchronously) 
                            channel.EndClose(result);
                    }
                }
            } 
            catch (Exception e)
            { 
                if (DiagnosticUtility.IsFatal(e)) 
                {
                    throw; 
                }
                this.HandleError(e);

                if (channel is ISessionChannel) 
                {
                    channel.Abort(); 
                } 
            }
        } 

        static void CloseChannelCallback(IAsyncResult result)
        {
            if (result.CompletedSynchronously) 
            {
                return; 
            } 

            CloseChannelState state = (CloseChannelState)result.AsyncState; 
            try
            {
                state.Channel.EndClose(result);
            } 
            catch (Exception e)
            { 
                if (DiagnosticUtility.IsFatal(e)) 
                {
                    throw; 
                }
                state.ListenerHandler.HandleError(e);
            }
        } 

        public void CloseInput(TimeSpan timeout) 
        { 
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            // Close all datagram channels 
            IChannel[] channels = this.channelDispatcher.Channels.ToArray();
            for (int index = 0; index < channels.Length; index++)
            {
                IChannel channel = channels[index]; 
                if (!this.IsSessionChannel(channel))
                { 
                    try 
                    {
                        channel.Close(timeoutHelper.RemainingTime()); 
                    }
                    catch (Exception e)
                    {
                        if (DiagnosticUtility.IsFatal(e)) 
                        {
                            throw; 
                        } 
                        this.HandleError(e);
                    } 
                }
            }
        }
 
        static void CloseOutputSessionCallback(IAsyncResult result)
        { 
            if (result.CompletedSynchronously) 
            {
                return; 
            }

            CloseChannelState state = (CloseChannelState)result.AsyncState;
            try 
            {
                ((ISessionChannel)state.Channel).Session.EndCloseOutputSession(result); 
            } 
            catch (Exception e)
            { 
                if (DiagnosticUtility.IsFatal(e))
                {
                    throw;
                } 
                state.ListenerHandler.HandleError(e);
                state.Channel.Abort(); 
            } 
        }
 
        void CloseChannels(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            IChannel[] channels = this.channelDispatcher.Channels.ToArray(); 
            for (int index = 0; index < channels.Length; index++)
                CloseChannel(channels[index], timeoutHelper.RemainingTime()); 
        } 

        void Dispatch() 
        {
            ListenerChannel channel = this.channel;
            SessionIdleManager idleManager = this.idleManager;
            this.channel = null; 
            this.idleManager = null;
 
            try 
            {
                if (channel != null) 
                {
                    ChannelHandler handler = new ChannelHandler(listenerBinder.MessageVersion, channel.Binder, this.throttle, this, (channel.Throttle != null), this.wrappedTransaction, idleManager);

                    if (!channel.Binder.HasSession) 
                    {
                        this.channelDispatcher.Channels.Add(channel.Binder.Channel); 
                    } 

                    if (channel.Binder is DuplexChannelBinder) 
                    {
                        DuplexChannelBinder duplexChannelBinder = channel.Binder as DuplexChannelBinder;
                        duplexChannelBinder.ChannelHandler = handler;
                        duplexChannelBinder.DefaultCloseTimeout = this.DefaultCloseTimeout; 

                        if (this.timeouts == null) 
                            duplexChannelBinder.DefaultSendTimeout = ServiceDefaults.SendTimeout; 
                        else
                            duplexChannelBinder.DefaultSendTimeout = timeouts.SendTimeout; 
                    }

                    ChannelHandler.Register(handler);
                    channel = null; 
                    idleManager = null;
                } 
            } 
            catch (Exception e)
            { 
                if (DiagnosticUtility.IsFatal(e))
                {
                    throw;
                } 
                this.HandleError(e);
            } 
            finally 
            {
                if (channel != null) 
                {
                    channel.Binder.Channel.Abort();
                    if (this.throttle != null && this.channelDispatcher.Session)
                    { 
                        this.throttle.DeactivateChannel();
                    } 
                    if (idleManager != null) 
                    {
                        idleManager.CancelTimer(); 
                    }
                }
            }
        } 

        void AcceptedNull() 
        { 
            this.acceptedNull = true;
        } 

        void DoneAccepting()
        {
            lock (this.ThisLock) 
            {
                if (!this.doneAccepting) 
                { 
                    this.doneAccepting = true;
                    this.channelDispatcher.Channels.DecrementActivityCount(); 
                }
            }
        }
 
        bool IsSessionChannel(IChannel channel)
        { 
            return (channel is ISessionChannel || 
                    channel is ISessionChannel ||
                    channel is ISessionChannel); 
        }

        void CancelPendingIdleManager()
        { 
            SessionIdleManager idleManager = this.idleManager;
            if (idleManager != null) 
            { 
                idleManager.CancelTimer();
            } 
        }

        protected override void OnAbort()
        { 
            // if there's an idle manager that has not been transferred to the channel handler, cancel it
            CancelPendingIdleManager(); 
 
            // Start aborting incoming channels
            this.channelDispatcher.Channels.CloseInput(); 

            // Abort existing channels
            this.AbortChannels();
 
            // Wait for channels to finish aborting
            this.channelDispatcher.Channels.Abort(); 
 
        }
 
        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
 
            // if there's an idle manager that has not been cancelled, cancel it
            CancelPendingIdleManager(); 
 
            // Start aborting incoming channels
            this.channelDispatcher.Channels.CloseInput(); 

            // Start closing existing channels
            this.CloseChannels(timeoutHelper.RemainingTime());
 
            // Wait for channels to finish closing
            return this.channelDispatcher.Channels.BeginClose(timeoutHelper.RemainingTime(), callback, state); 
        } 

        protected override void OnClose(TimeSpan timeout) 
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);

            // if there's an idle manager that has not been cancelled, cancel it 
            CancelPendingIdleManager();
 
            // Start aborting incoming channels 
            this.channelDispatcher.Channels.CloseInput();
 
            // Start closing existing channels
            this.CloseChannels(timeoutHelper.RemainingTime());

            // Wait for channels to finish closing 
            this.channelDispatcher.Channels.Close(timeoutHelper.RemainingTime());
        } 
 
        protected override void OnEndClose(IAsyncResult result)
        { 
            this.channelDispatcher.Channels.EndClose(result);
        }

        bool HandleError(Exception e) 
        {
            return this.channelDispatcher.HandleError(e); 
        } 

        class CloseChannelState 
        {
            ListenerHandler listenerHandler;
            IChannel channel;
 
            internal CloseChannelState(ListenerHandler listenerHandler, IChannel channel)
            { 
                this.listenerHandler = listenerHandler; 
                this.channel = channel;
            } 

            internal ListenerHandler ListenerHandler
            {
                get { return this.listenerHandler; } 
            }
 
            internal IChannel Channel 
            {
                get { return this.channel; } 
            }
        }
    }
 
    class ListenerChannel
    { 
        IChannelBinder binder; 
        ServiceThrottle throttle;
 
        public ListenerChannel(IChannelBinder binder)
        {
            this.binder = binder;
        } 

        public IChannelBinder Binder 
        { 
            get { return this.binder; }
        } 

        public ServiceThrottle Throttle
        {
            get { return this.throttle; } 
            set { this.throttle = value; }
        } 
    } 

    class WrappedTransaction 
    {
        Transaction transaction;

        internal WrappedTransaction(Transaction transaction) 
        {
            this.transaction = transaction; 
        } 

        internal Transaction Transaction 
        {
            get { return this.transaction; }
        }
    } 
}

// 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