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

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

namespace System.ServiceModel.Channels 
{
    using System.Diagnostics; 
    using System.ServiceModel; 
    using System.ServiceModel.Diagnostics;
    using System.ServiceModel.Dispatcher; 
    using System.Threading;

    delegate void ConnectionAvailableCallback(IConnection connection, ItemDequeuedCallback connectionDequeuedCallback);
    delegate void ErrorCallback(Exception exception); 

    class ConnectionAcceptor : IDisposable 
    { 
        int maxAccepts;
        int maxPendingConnections; 
        int connections;
        int pendingAccepts;
        IConnectionListener listener;
        AsyncCallback acceptCompletedCallback; 
        WaitCallback scheduleAcceptCallback;
        ItemDequeuedCallback onConnectionDequeued; 
        bool isDisposed; 
        ConnectionAvailableCallback callback;
        ErrorCallback errorCallback; 

        public ConnectionAcceptor(IConnectionListener listener, int maxAccepts, int maxPendingConnections,
            ConnectionAvailableCallback callback)
            : this(listener, maxAccepts, maxPendingConnections, callback, null) 
        {
            // empty 
        } 

        public ConnectionAcceptor(IConnectionListener listener, int maxAccepts, int maxPendingConnections, 
            ConnectionAvailableCallback callback, ErrorCallback errorCallback)
        {
            if (maxAccepts <= 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxAccepts", maxAccepts,
                    SR.GetString(SR.ValueMustBePositive))); 
            } 

            DiagnosticUtility.DebugAssert(maxPendingConnections > 0, "maxPendingConnections must be positive"); 

            this.listener = listener;
            this.maxAccepts = maxAccepts;
            this.maxPendingConnections = maxPendingConnections; 
            this.callback = callback;
            this.errorCallback = errorCallback; 
            this.onConnectionDequeued = new ItemDequeuedCallback(OnConnectionDequeued); 
            this.acceptCompletedCallback = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(AcceptCompletedCallback));
            this.scheduleAcceptCallback = new WaitCallback(ScheduleAcceptCallback); 
        }

        bool IsAcceptNecessary
        { 
            get
            { 
                return (pendingAccepts < maxAccepts) 
                    && ((connections + pendingAccepts) < maxPendingConnections)
                    && !isDisposed; 
            }
        }

        public int ConnectionCount 
        {
            get { return connections; } 
        } 

        object ThisLock 
        {
            get { return this; }
        }
 
        void AcceptIfNecessary(bool startAccepting)
        { 
            if (IsAcceptNecessary) 
            {
                lock (ThisLock) 
                {
                    while (IsAcceptNecessary)
                    {
                        IAsyncResult result = null; 
                        Exception unexpectedException = null;
                        try 
                        { 
                            result = listener.BeginAccept(acceptCompletedCallback, null);
                        } 
                        catch (CommunicationException exception)
                        {
                            if (DiagnosticUtility.ShouldTraceInformation)
                            { 
                                DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information);
                            } 
                        } 
                        catch (Exception exception)
                        { 
                            if (DiagnosticUtility.IsFatal(exception))
                            {
                                throw;
                            } 
                            if (startAccepting)
                            { 
                                // Since we're under a call to StartAccepting(), just throw the exception up the stack. 
                                throw;
                            } 
                            if ((errorCallback == null) && !ExceptionHandler.HandleTransportExceptionHelper(exception))
                            {
                                throw;
                            } 
                            unexpectedException = exception;
                        } 
 
                        if ((unexpectedException != null) && (errorCallback != null))
                        { 
                            errorCallback(unexpectedException);
                        }

                        if (result != null) 
                        {
                            // don't block our accept processing loop 
                            if (result.CompletedSynchronously) 
                            {
                                IOThreadScheduler.ScheduleCallback(scheduleAcceptCallback, result); 
                            }

                            pendingAccepts++;
                        } 
                    }
                } 
            } 
        }
 
        void AcceptCompletedCallback(IAsyncResult result)
        {
            if (result.CompletedSynchronously)
            { 
                return;
            } 
 
            HandleCompletedAccept(result);
        } 

        public void Dispose()
        {
            lock (ThisLock) 
            {
                if (!isDisposed) 
                { 
                    isDisposed = true;
                    listener.Dispose(); 
                }
            }
        }
 
        void HandleCompletedAccept(IAsyncResult result)
        { 
            IConnection connection = null; 

            lock (ThisLock) 
            {
                bool success = false;
                Exception unexpectedException = null;
                try 
                {
                    if (!isDisposed) 
                    { 
                        connection = listener.EndAccept(result);
                        if (connection != null) 
                        {
                            if (DiagnosticUtility.ShouldTraceWarning)
                            {
                                if (connections + 1 >= maxPendingConnections) 
                                {
                                    TraceUtility.TraceEvent(TraceEventType.Warning, 
                                        TraceCode.MaxPendingConnectionsReached, 
                                        new StringTraceRecord("MaxPendingConnections", maxPendingConnections.ToString(System.Globalization.CultureInfo.InvariantCulture)),
                                        this, 
                                        null);
                                }
                            }
 
                            // This is incremented after the Trace just in case the Trace throws.
                            connections++; 
                        } 
                    }
                    success = true; 
                }
                catch (CommunicationException exception)
                {
                    if (DiagnosticUtility.ShouldTraceInformation) 
                    {
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information); 
                    } 
                }
                catch (Exception exception) 
                {
                    if (DiagnosticUtility.IsFatal(exception))
                    {
                        throw; 
                    }
                    if ((errorCallback == null) && !ExceptionHandler.HandleTransportExceptionHelper(exception)) 
                    { 
                        throw;
                    } 
                    unexpectedException = exception;
                }
                finally
                { 
                    if (!success)
                    { 
                        connection = null; 
                    }
                    pendingAccepts--; 
                }

                if ((unexpectedException != null) && (errorCallback != null))
                { 
                    errorCallback(unexpectedException);
                } 
            } 

            AcceptIfNecessary(false); 

            if (connection != null)
            {
                callback(connection, onConnectionDequeued); 
            }
        } 
 
        void OnConnectionDequeued()
        { 
            lock (ThisLock)
            {
                connections--;
            } 
            AcceptIfNecessary(false);
        } 
 
        void ScheduleAcceptCallback(object state)
        { 
            HandleCompletedAccept((IAsyncResult)state);
        }

        public void StartAccepting() 
        {
            listener.Listen(); 
            AcceptIfNecessary(true); 
        }
    } 
}

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