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

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

namespace System.ServiceModel.Channels 
{
    using System.Diagnostics; 
    using System.ServiceModel; 
    using System.ServiceModel.Activation;
    using System.ServiceModel.Dispatcher; 
    using System.IO;
    using System.Threading;
    using System.Collections.Generic;
    using System.Globalization; 
    using System.ServiceModel.Diagnostics;
 
    sealed class ConnectionDemuxer : IDisposable 
    {
        ConnectionAcceptor acceptor; 

        // we use this list to track readers that don't have a clear owner (so they don't get GC'ed)
        List connectionReaders;
 
        bool isDisposed;
        ConnectionModeCallback onConnectionModeKnown; 
        ConnectionModeCallback onCachedConnectionModeKnown; 
        ConnectionClosedCallback onConnectionClosed;
        ServerSessionPreambleCallback onSessionPreambleKnown; 
        ServerSingletonPreambleCallback onSingletonPreambleKnown;
        WaitCallback reuseConnectionCallback;
        ServerSessionPreambleDemuxCallback serverSessionPreambleCallback;
        SingletonPreambleDemuxCallback singletonPreambleCallback; 
        TransportSettingsCallback transportSettingsCallback;
        ItemDequeuedCallback pooledConnectionDequeuedCallback; 
        OnViaDelegate viaDelegate; 
        TimeSpan channelInitializationTimeout;
        TimeSpan idleTimeout; 
        int maxPooledConnections;
        int pooledConnectionCount;

        public ConnectionDemuxer(IConnectionListener listener, int maxAccepts, int maxPendingConnections, 
            TimeSpan channelInitializationTimeout, TimeSpan idleTimeout, int maxPooledConnections,
            TransportSettingsCallback transportSettingsCallback, 
            SingletonPreambleDemuxCallback singletonPreambleCallback, 
            ServerSessionPreambleDemuxCallback serverSessionPreambleCallback, ErrorCallback errorCallback)
        { 
            this.connectionReaders = new List();
            this.acceptor =
                new ConnectionAcceptor(listener, maxAccepts, maxPendingConnections, OnConnectionAvailable, errorCallback);
            this.channelInitializationTimeout = channelInitializationTimeout; 
            this.idleTimeout = idleTimeout;
            this.maxPooledConnections = maxPooledConnections; 
            this.onConnectionClosed = new ConnectionClosedCallback(OnConnectionClosed); 
            this.transportSettingsCallback = transportSettingsCallback;
            this.singletonPreambleCallback = singletonPreambleCallback; 
            this.serverSessionPreambleCallback = serverSessionPreambleCallback;
        }

        object ThisLock 
        {
            get { return this; } 
        } 

        public void Dispose() 
        {
            lock (ThisLock)
            {
                if (isDisposed) 
                    return;
 
                isDisposed = true; 
            }
 
            for (int i = 0; i < connectionReaders.Count; i++)
            {
                connectionReaders[i].Dispose();
            } 
            connectionReaders.Clear();
 
            acceptor.Dispose(); 
        }
 
        ConnectionModeReader SetupModeReader(IConnection connection, bool isCached)
        {
            ConnectionModeReader modeReader;
            if (isCached) 
            {
                if (onCachedConnectionModeKnown == null) 
                { 
                    onCachedConnectionModeKnown = new ConnectionModeCallback(OnCachedConnectionModeKnown);
                } 

                modeReader = new ConnectionModeReader(connection, onCachedConnectionModeKnown, onConnectionClosed);
            }
            else 
            {
                if (onConnectionModeKnown == null) 
                { 
                    onConnectionModeKnown = new ConnectionModeCallback(OnConnectionModeKnown);
                } 

                modeReader = new ConnectionModeReader(connection, onConnectionModeKnown, onConnectionClosed);
            }
 
            lock (ThisLock)
            { 
                if (isDisposed) 
                {
                    modeReader.Dispose(); 
                    return null;
                }

                connectionReaders.Add(modeReader); 
                return modeReader;
            } 
        } 

        public void ReuseConnection(IConnection connection, TimeSpan closeTimeout) 
        {
            connection.ExceptionEventType = TraceEventType.Information;
            ConnectionModeReader modeReader = SetupModeReader(connection, true);
 
            if (modeReader != null)
            { 
                if (reuseConnectionCallback == null) 
                {
                    reuseConnectionCallback = new WaitCallback(ReuseConnectionCallback); 
                }

                IOThreadScheduler.ScheduleCallback(reuseConnectionCallback, new ReuseConnectionState(modeReader, closeTimeout));
            } 
        }
 
        void ReuseConnectionCallback(object state) 
        {
            ReuseConnectionState connectionState = (ReuseConnectionState)state; 
            bool closeReader = false;
            lock (ThisLock)
            {
                if (this.pooledConnectionCount >= this.maxPooledConnections) 
                {
                    closeReader = true; 
                } 
                else
                { 
                    this.pooledConnectionCount++;
                }
            }
 
            if (closeReader)
            { 
                if (DiagnosticUtility.ShouldTraceWarning) 
                {
                    DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Warning, 
                        TraceCode.ServerMaxPooledConnectionsQuotaReached,
                        SR.GetString(SR.TraceCodeServerMaxPooledConnectionsQuotaReached, maxPooledConnections),
                        new StringTraceRecord("MaxOutboundConnectionsPerEndpoint", maxPooledConnections.ToString(CultureInfo.InvariantCulture)),
                        null, this); 
                }
                connectionState.ModeReader.CloseFromPool(connectionState.CloseTimeout); 
            } 
            else
            { 
                if (this.pooledConnectionDequeuedCallback == null)
                {
                    this.pooledConnectionDequeuedCallback = new ItemDequeuedCallback(PooledConnectionDequeuedCallback);
                } 
                connectionState.ModeReader.StartReading(this.idleTimeout, this.pooledConnectionDequeuedCallback);
            } 
        } 

        void PooledConnectionDequeuedCallback() 
        {
            lock (ThisLock)
            {
                this.pooledConnectionCount--; 
                DiagnosticUtility.DebugAssert(this.pooledConnectionCount >= 0, "Connection Throttle should never be negative");
            } 
        } 

        void OnConnectionAvailable(IConnection connection, ItemDequeuedCallback connectionDequeuedCallback) 
        {
            ConnectionModeReader modeReader = SetupModeReader(connection, false);

            if (modeReader != null) 
            {
                // StartReading() will never throw non-fatal exceptions; 
                // it propagates all exceptions into the onConnectionModeKnown callback, 
                // which is where we need our robust handling
                modeReader.StartReading(this.channelInitializationTimeout, connectionDequeuedCallback); 
            }
            else
            {
                connectionDequeuedCallback(); 
            }
        } 
 
        void OnCachedConnectionModeKnown(ConnectionModeReader modeReader)
        { 
            OnConnectionModeKnownCore(modeReader, true);
        }

        void OnConnectionModeKnown(ConnectionModeReader modeReader) 
        {
            OnConnectionModeKnownCore(modeReader, false); 
        } 

        void OnConnectionModeKnownCore(ConnectionModeReader modeReader, bool isCached) 
        {
            lock (ThisLock)
            {
                if (isDisposed) 
                    return;
 
                this.connectionReaders.Remove(modeReader); 
            }
 
            bool closeReader = true;
            try
            {
                FramingMode framingMode; 
                try
                { 
                    framingMode = modeReader.GetConnectionMode(); 
                }
                catch (CommunicationException exception) 
                {
                    TraceEventType eventType = modeReader.Connection.ExceptionEventType;
                    if (DiagnosticUtility.ShouldTrace(eventType))
                    { 
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, eventType);
                    } 
                    return; 
                }
                catch (TimeoutException exception) 
                {
                    if (!isCached)
                    {
                        exception = new TimeoutException(SR.GetString(SR.ChannelInitializationTimeout, this.channelInitializationTimeout), exception); 
                        System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(exception);
                    } 
 
                    TraceEventType eventType = modeReader.Connection.ExceptionEventType;
                    if (DiagnosticUtility.ShouldTrace(eventType)) 
                    {
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, eventType);
                    }
                    return; 
                }
 
                switch (framingMode) 
                {
                    case FramingMode.Duplex: 
                        OnDuplexConnection(modeReader.Connection, modeReader.ConnectionDequeuedCallback,
                            modeReader.StreamPosition, modeReader.BufferOffset, modeReader.BufferSize,
                            modeReader.GetRemainingTimeout());
                        break; 

                    case FramingMode.Singleton: 
                        OnSingletonConnection(modeReader.Connection, modeReader.ConnectionDequeuedCallback, 
                            modeReader.StreamPosition, modeReader.BufferOffset, modeReader.BufferSize,
                            modeReader.GetRemainingTimeout()); 
                        break;

                    default:
                    { 
                        Exception inner = new InvalidDataException(SR.GetString(
                            SR.FramingModeNotSupported, framingMode)); 
                        Exception exception = new ProtocolException(inner.Message, inner); 
                        FramingEncodingString.AddFaultString(exception, FramingEncodingString.UnsupportedModeFault);
                        System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(exception); 
                        return;
                    }
                }
 
                closeReader = false;
            } 
            catch (Exception e) 
            {
                if (DiagnosticUtility.IsFatal(e)) 
                {
                    throw;
                }
                if (!ExceptionHandler.HandleTransportExceptionHelper(e)) 
                {
                    throw; 
                } 

                // containment -- the reader is aborted, no need for additional containment 
            }
            finally
            {
                if (closeReader) 
                {
                    modeReader.Dispose(); 
                } 
            }
        } 

        void OnConnectionClosed(InitialServerConnectionReader connectionReader)
        {
            lock (ThisLock) 
            {
                if (isDisposed) 
                    return; 

                connectionReaders.Remove(connectionReader); 
            }
        }

        void OnSingletonConnection(IConnection connection, ItemDequeuedCallback connectionDequeuedCallback, 
            long streamPosition, int offset, int size, TimeSpan timeout)
        { 
            if (onSingletonPreambleKnown == null) 
            {
                onSingletonPreambleKnown = OnSingletonPreambleKnown; 
            }
            ServerSingletonPreambleConnectionReader singletonPreambleReader =
                new ServerSingletonPreambleConnectionReader(connection, connectionDequeuedCallback, streamPosition, offset, size,
                transportSettingsCallback, onConnectionClosed, onSingletonPreambleKnown); 

            lock (ThisLock) 
            { 
                if (isDisposed)
                { 
                    singletonPreambleReader.Dispose();
                    return;
                }
 
                connectionReaders.Add(singletonPreambleReader);
            } 
            singletonPreambleReader.StartReading(viaDelegate, timeout); 
        }
 
        void OnSingletonPreambleKnown(ServerSingletonPreambleConnectionReader serverSingletonPreambleReader)
        {
            lock (ThisLock)
            { 
                if (isDisposed)
                { 
                    return; 
                }
 
                connectionReaders.Remove(serverSingletonPreambleReader);
            }

            ISingletonChannelListener singletonChannelListener = singletonPreambleCallback(serverSingletonPreambleReader); 
            DiagnosticUtility.DebugAssert(singletonChannelListener != null,
                "singletonPreambleCallback must return a listener or send a Fault/throw"); 
 
            // transfer ownership of the connection from the preamble reader to the message handler
            TimeoutHelper timeoutHelper = new TimeoutHelper(singletonChannelListener.ReceiveTimeout); 
            IConnection upgradedConnection = serverSingletonPreambleReader.CompletePreamble(timeoutHelper.RemainingTime());
            ServerSingletonConnectionReader singletonReader =
                new ServerSingletonConnectionReader(serverSingletonPreambleReader, upgradedConnection, this);
            RequestContext requestContext = singletonReader.ReceiveRequest(timeoutHelper.RemainingTime()); 
            singletonChannelListener.ReceiveRequest(requestContext, serverSingletonPreambleReader.ConnectionDequeuedCallback, true);
        } 
 
        void OnSessionPreambleKnown(ServerSessionPreambleConnectionReader serverSessionPreambleReader)
        { 
            lock (ThisLock)
            {
                if (isDisposed)
                { 
                    return;
                } 
 
                connectionReaders.Remove(serverSessionPreambleReader);
            } 

            serverSessionPreambleCallback(serverSessionPreambleReader, this);
        }
 
        void OnDuplexConnection(IConnection connection, ItemDequeuedCallback connectionDequeuedCallback,
            long streamPosition, int offset, int size, TimeSpan timeout) 
        { 
            if (onSessionPreambleKnown == null)
            { 
                onSessionPreambleKnown = OnSessionPreambleKnown;
            }
            ServerSessionPreambleConnectionReader sessionPreambleReader = new ServerSessionPreambleConnectionReader(
                connection, connectionDequeuedCallback, streamPosition, offset, size, 
                transportSettingsCallback, onConnectionClosed, onSessionPreambleKnown);
            lock (ThisLock) 
            { 
                if (isDisposed)
                { 
                    sessionPreambleReader.Dispose();
                    return;
                }
 
                connectionReaders.Add(sessionPreambleReader);
            } 
 
            sessionPreambleReader.StartReading(viaDelegate, timeout);
        } 

        public void StartDemuxing()
        {
            StartDemuxing(null); 
        }
 
        public void StartDemuxing(OnViaDelegate viaDelegate) 
        {
            this.viaDelegate = viaDelegate; 
            acceptor.StartAccepting();
        }

        class ReuseConnectionState 
        {
            ConnectionModeReader modeReader; 
            TimeSpan closeTimeout; 

            public ReuseConnectionState(ConnectionModeReader modeReader, TimeSpan closeTimeout) 
            {
                this.modeReader = modeReader;
                this.closeTimeout = closeTimeout;
            } 

            public ConnectionModeReader ModeReader 
            { 
                get { return this.modeReader; }
            } 

            public TimeSpan CloseTimeout
            {
                get { return this.closeTimeout; } 
            }
        } 
    } 
}

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