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

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

namespace System.ServiceModel.Channels 
{
    using System.Collections.Generic; 
    using System.ServiceModel; 
    using System.ComponentModel;
    using System.Diagnostics; 
    using System.Net;
    using System.Net.Sockets;
    using System.Security.Principal;
    using System.ServiceModel.Diagnostics; 
    using System.Threading;
    using System.ServiceProcess; 
    using System.Security.AccessControl; 
    using System.Reflection;
    using System.ServiceModel.Configuration; 
    using System.Web.Hosting;
    using System.ServiceModel.Security;
    using System.ServiceModel.Activation;
    using System.Runtime.InteropServices; 
    using System.Runtime.CompilerServices;
    using System.Runtime.Remoting; 
    using System.ServiceModel.Dispatcher; 
    using System.ServiceModel.Description;
 
    using Utility = System.ServiceModel.Activation.Utility;


    sealed class SharedConnectionListener : IConnectionListener 
    {
        BaseUriWithWildcard baseAddress; 
        int queueId; 
        Guid token;
        InputQueue connectionQueue; 
        SharedListenerProxy listenerProxy;
        WaitCallback reconnectCallback;
        object syncRoot = new object();
        CommunicationState state; 
        ManualResetEvent reconnectEvent;
        OnDuplicatedViaDelegate onDuplicatedViaCallback; 
 
        internal SharedConnectionListener(BaseUriWithWildcard baseAddress, int queueId, Guid token,
            OnDuplicatedViaDelegate onDuplicatedViaCallback) 
        {
            this.baseAddress = baseAddress;
            this.queueId = queueId;
            this.token = token; 
            this.onDuplicatedViaCallback = onDuplicatedViaCallback;
 
            this.connectionQueue = new InputQueue(); 
            this.state = CommunicationState.Created;
            this.reconnectEvent = new ManualResetEvent(true); 

            // only attmptStart if doing TCP port sharing
            // for activation we need to wait for the service to start if it crashes before w3wp can hook up
            StartListen(false); 
        }
 
        object ThisLock 
        {
            get 
            {
                return this.syncRoot;
            }
        } 

        void IConnectionListener.Listen() 
        { 
            // No-op since we have already been started.
        } 

        IAsyncResult IConnectionListener.BeginAccept(AsyncCallback callback, object state)
        {
            DiagnosticUtility.DebugAssert(connectionQueue != null, "The connectionQueue should not be null when BeginAccept is called."); 
            Debug.Print("SharedConnectionListener.BeginAccept() connectionQueue.PendingCount: " + connectionQueue.PendingCount);
            return connectionQueue.BeginDequeue(TimeSpan.MaxValue, callback, state); 
        } 

        // Stop the proxy but do not close to let existing connections to be drained. 
        public void Stop()
        {
            bool shouldWait = false;
            lock (ThisLock) 
            {
                if (this.state == CommunicationState.Closing || 
                    this.state == CommunicationState.Closed) 
                {
                    return; 
                }
                else if (this.state == CommunicationState.Opening)
                {
                    shouldWait = true; 
                }
 
                this.state = CommunicationState.Closing; 
            }
 
            if (shouldWait)
            {
                this.reconnectEvent.WaitOne();
            } 

            if (listenerProxy != null) 
            { 
                listenerProxy.Close();
            } 
        }

        void Close()
        { 
            lock (ThisLock)
            { 
                if (this.state == CommunicationState.Closed) 
                {
                    return; 
                }

                DiagnosticUtility.DebugAssert(this.state == CommunicationState.Closing,
                    "The Stop method must be called first before calling Close."); 

                this.state = CommunicationState.Closed; 
            } 

            if (connectionQueue != null) 
            {
                connectionQueue.Close();
            }
 
            if (this.reconnectEvent != null)
            { 
                this.reconnectEvent.Close(); 
            }
        } 

        void OnConnectionAvailable(DuplicateConnectionAsyncResult result)
        {
            // Enqueue the context and dispatch it on a different thread. 
            connectionQueue.EnqueueAndDispatch(result, null, false);
        } 
 
        static string GetServiceName(bool isTcp)
        { 
            return isTcp ? ListenerConstants.TcpPortSharingServiceName : ListenerConstants.NamedPipeActivationServiceName;
        }

        IConnection IConnectionListener.EndAccept(IAsyncResult result) 
        {
            lock (ThisLock) 
            { 
                if (this.state != CommunicationState.Opening &&
                    this.state != CommunicationState.Opened) 
                {
                    return null;
                }
 
                DuplicateConnectionAsyncResult duplicateAsyncResult = connectionQueue.EndDequeue(result);
                DiagnosticUtility.DebugAssert(duplicateAsyncResult != null, "EndAccept: EndDequeue returned null."); 
 
                // Finish the duplication.
                duplicateAsyncResult.CompleteOperation(); 

                return duplicateAsyncResult.Connection;
            }
        } 

        void OnListenerFaulted(bool shouldReconnect) 
        { 
            lock (ThisLock)
            { 
                if (this.state == CommunicationState.Closing ||
                    this.state == CommunicationState.Closed)
                {
                    return; 
                }
 
                listenerProxy.Abort(); 

                if (shouldReconnect) 
                {
                    this.state = CommunicationState.Opening;
                    this.reconnectEvent.Reset();
                } 
                else
                { 
                    this.state = CommunicationState.Faulted; 
                }
            } 

            if (shouldReconnect)
            {
                if (reconnectCallback == null) 
                {
                    reconnectCallback = new WaitCallback(ReconnectCallback); 
                } 

                IOThreadScheduler.ScheduleCallback(reconnectCallback, this); 
            }
        }

        void StartListen(bool isReconnecting) 
        {
            listenerProxy = new SharedListenerProxy(this); 
            if (isReconnecting) 
            {
                // Signal the event so that we are safe to close. 
                reconnectEvent.Set();
            }

            listenerProxy.Open(isReconnecting); 

            lock (ThisLock) 
            { 
                if (this.state == CommunicationState.Created || this.state == CommunicationState.Opening)
                { 
                    this.state = CommunicationState.Opened;
                }
            }
        } 

        void ReconnectCallback(object state) 
        { 
            BackoffTimeoutHelper backoffHelper =
                new BackoffTimeoutHelper(TimeSpan.MaxValue, TimeSpan.FromMinutes(5), TimeSpan.FromSeconds(30)); 

            // Looping until we can connect or when it's closed.
            while(this.state == CommunicationState.Opening)
            { 
                bool success = false;
                try 
                { 
                    StartListen(true);
                    success = true; 
                }
                catch (Exception exception)
                {
                    if (DiagnosticUtility.IsFatal(exception)) 
                    {
                        throw; 
                    } 

                    if (DiagnosticUtility.ShouldTraceError) 
                    {
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Error);
                    }
                } 

                // Add backoff when reconnect 
                if (this.state == CommunicationState.Opening) 
                {
                    DiagnosticUtility.DebugAssert(!success, "The state should be Opened if it is successful."); 
                    backoffHelper.WaitAndBackoff();
                }
            }
        } 

        void IDisposable.Dispose() 
        { 
            Debug.Print("SharedConnectionListener.Dispose()");
            Close(); 
        }

        [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
        class SharedListenerProxy : IConnectionDuplicator, IInputSessionShutdown 
        {
            static byte[] drainBuffer; 
            SharedConnectionListener parent; 
            BaseUriWithWildcard baseAddress;
            int queueId; 
            Guid token;
            bool isTcp;
            string serviceName;
            string listenerEndPoint; 
            SecurityIdentifier listenerUniqueSid;
            SecurityIdentifier listenerUserSid; 
            ChannelFactory channelFactory; 
            IDuplexContextChannel controlSessionWithListener;
            IDisposable allowContext; 
            string securityEventName;
            object syncRoot = new object();
            int connectionBufferSize;
            OnDuplicatedViaDelegate onDuplicatedViaCallback; 
            bool listenerClosed;
            bool closed; 
            bool opened; 

            public SharedListenerProxy(SharedConnectionListener parent) 
            {
                this.parent = parent;
                this.baseAddress = parent.baseAddress;
                this.queueId = parent.queueId; 
                this.token = parent.token;
                this.onDuplicatedViaCallback = parent.onDuplicatedViaCallback; 
                this.isTcp = parent.baseAddress.BaseAddress.Scheme.Equals(Uri.UriSchemeNetTcp); 
                this.securityEventName = Guid.NewGuid().ToString();
                this.serviceName = SharedConnectionListener.GetServiceName(isTcp); 
            }

            public void Open(bool isReconnecting)
            { 
                Debug.Print("SharedListenerProxy.Open() isReconnecting: " + isReconnecting);
 
                if (this.closed) 
                {
                    return; 
                }

                // Start the listener service
                this.listenerEndPoint = HandleServiceStart(isReconnecting); 
                if (string.IsNullOrEmpty(listenerEndPoint))
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( 
                        SR.GetString(SR.Sharing_EmptyListenerEndpoint, this.serviceName)));
                } 

                // Check it again after possible backoff
                if (this.closed)
                { 
                    return;
                } 
 
                LookupListenerSid();
 
                EventWaitHandle securityEvent = null;
                bool success = false;

                // Synchronize with Close so that we can ensure cleanness 
                lock (ThisLock)
                { 
                    try 
                    {
                        // Create the control proxy 
                        CreateControlProxy();

                        EventWaitHandleSecurity handleSecurity = new EventWaitHandleSecurity();
                        handleSecurity.AddAccessRule(new EventWaitHandleAccessRule(listenerUniqueSid, EventWaitHandleRights.Modify, AccessControlType.Allow)); 

                        bool createdNew; 
                        securityEvent = new EventWaitHandle(false, EventResetMode.ManualReset, ListenerConstants.GlobalPrefix + this.securityEventName, out createdNew, handleSecurity); 
                        if (!createdNew)
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SharedManagerBase, serviceName, SR.GetString(SR.SharedManagerServiceSecurityFailed))));
                        }

                        Register(); 

                        bool signalled = securityEvent.WaitOne(0, false); 
                        if (!signalled) 
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SharedManagerBase, serviceName, SR.GetString(SR.SharedManagerServiceSecurityFailed)))); 
                        }

                        if (DiagnosticUtility.ShouldTraceInformation)
                        { 
                            TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PortSharingListening, SR.GetString(SR.TraceCodePortSharingListening));
                        } 
 
                        this.opened = true;
                        success = true; 
                    }
                    finally
                    {
                        if (securityEvent != null) 
                        {
                            securityEvent.Close(); 
                        } 

                        if (!success) 
                        {
                            Cleanup(true);

                            // Mark it as closed 
                            this.closed = true;
                        } 
                    } 
                }
            } 

            public void Close()
            {
                Close(false); 
            }
 
            void Close(bool isAborting) 
            {
                lock (ThisLock) 
                {
                    if (this.closed)
                    {
                        return; 
                    }
 
                    bool success = false; 
                    try
                    { 
                        Cleanup(isAborting);
                        success = true;
                    }
                    finally 
                    {
                        if (!success && !isAborting) 
                        { 
                            // Abort it
                            Close(true); 
                        }

                        this.closed = true;
                    } 
                }
 
                if (DiagnosticUtility.ShouldTraceInformation) 
                {
                    TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PortSharingClosed, SR.GetString(SR.TraceCodePortSharingClosed)); 
                }
            }

            void Cleanup(bool isAborting) 
            {
                bool success = false; 
                if (controlSessionWithListener != null) 
                {
                    if (!isAborting) 
                    {
                        try
                        {
                            Unregister(); 
                            controlSessionWithListener.Close(ListenerConstants.RegistrationCloseTimeout);
                            success = true; 
                        } 
                        catch (Exception exception)
                        { 
                            if (DiagnosticUtility.IsFatal(exception))
                            {
                                throw;
                            } 

                            if (DiagnosticUtility.ShouldTraceError) 
                            { 
                                DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Error);
                            } 
                        }
                    }

                    if (isAborting || !success) 
                    {
                        controlSessionWithListener.Abort(); 
                    } 
                }
 
                if (channelFactory != null)
                {
                    success = false;
                    if (!isAborting) 
                    {
                        try 
                        { 
                            channelFactory.Close(ListenerConstants.RegistrationCloseTimeout);
                            success = true; 
                        }
                        catch(Exception exception)
                        {
                            if (DiagnosticUtility.IsFatal(exception)) 
                            {
                                throw; 
                            } 

                            if (DiagnosticUtility.ShouldTraceError) 
                            {
                                DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Error);
                            }
                        } 
                    }
 
                    if (isAborting || !success) 
                    {
                        channelFactory.Abort(); 
                    }
                }

                if (allowContext != null) 
                {
                    allowContext.Dispose(); 
                } 
            }
 
            public void Abort()
            {
                Close(true);
            } 

            object ThisLock 
            { 
                get
                { 
                    return this.syncRoot;
                }
            }
 
            void Unregister()
            { 
                Debug.Print("SharedListenerProxy.Unregister()"); 
                ((IConnectionRegister)controlSessionWithListener).Unregister();
            } 

            void LookupListenerSid()
            {
                // SECURITY 
                // now check with the SCM and get the LogonSid or ServiceSid and the Pid for the listener
                if (OSEnvironmentHelper.IsVistaOrGreater) 
                { 
                    try
                    { 
                        listenerUniqueSid = Utility.GetWindowsServiceSid(serviceName);
                        Debug.Print("SharedListenerProxy.LookupListenerSid() listenerUniqueSid: " + listenerUniqueSid);
                    }
                    catch (Win32Exception exception) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SharedManagerBase, serviceName, SR.GetString(SR.SharedManagerServiceSidLookupFailure, exception.NativeErrorCode)), exception)); 
                    } 
                }
                else 
                {
                    int listenerPid;
                    try
                    { 
                        listenerPid = Utility.GetPidForService(serviceName);
                        Debug.Print("SharedListenerProxy.LookupListenerSid() listenerPid: " + listenerPid); 
                    } 
                    catch (Win32Exception exception)
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SharedManagerBase, serviceName, SR.GetString(SR.SharedManagerServiceLookupFailure, exception.NativeErrorCode)), exception));
                    }
                    try
                    { 
                        listenerUserSid = Utility.GetUserSidForPid(listenerPid);
                        Debug.Print("SharedListenerProxy.LookupListenerSid() listenerUserSid: " + listenerUserSid); 
                    } 
                    catch (Win32Exception exception)
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SharedManagerBase, serviceName, SR.GetString(SR.SharedManagerUserSidLookupFailure, exception.NativeErrorCode)), exception));
                    }
                    try
                    { 
                        listenerUniqueSid = Utility.GetLogonSidForPid(listenerPid);
                    } 
                    catch (Win32Exception exception) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SharedManagerBase, serviceName, SR.GetString(SR.SharedManagerLogonSidLookupFailure, exception.NativeErrorCode)), exception)); 
                    }
                }

                Debug.Print("SharedListenerProxy.LookupListenerSid() listenerUniqueSid: " + listenerUniqueSid); 
            }
 
            void CreateControlProxy() 
            {
                EndpointAddress epa = new EndpointAddress(Utility.FormatListenerEndpoint(this.serviceName, 
                    this.listenerEndPoint));

                NamedPipeTransportBindingElement namedPipeBindingElement = new NamedPipeTransportBindingElement();
                CustomBinding customBinding = new CustomBinding(namedPipeBindingElement); 
                InstanceContext instanceContext = new InstanceContext(null, this, false);
 
                ChannelFactory registerChannelFactory = new DuplexChannelFactory(instanceContext, 
                    customBinding, epa);
 
                registerChannelFactory.Endpoint.Behaviors.Add(new SharedListenerProxyBehavior(this));

                IConnectionRegister connectionRegister = registerChannelFactory.CreateChannel();
                this.channelFactory = registerChannelFactory; 
                this.controlSessionWithListener = connectionRegister as IDuplexContextChannel;
            } 
 
            void Register()
            { 
                Version version = Assembly.GetExecutingAssembly().GetName().Version;
                int myPid = Process.GetCurrentProcess().Id;

                HandleAllowDupHandlePermission(myPid); 

                ListenerExceptionStatus status = ((IConnectionRegister)this.controlSessionWithListener).Register( 
                        version, myPid, this.baseAddress, this.queueId, this.token, this.securityEventName); 

                Debug.Print("SharedListenerProxy.Register() Register returned status: " + status); 
                if (status != ListenerExceptionStatus.Success)
                {
                    switch (status)
                    { 
                        case ListenerExceptionStatus.ConflictingRegistration:
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AddressAlreadyInUseException(SR.GetString(SR.SharedManagerBase, serviceName, SR.GetString(SR.SharedManagerConflictingRegistration)))); 
                        case ListenerExceptionStatus.FailedToListen: 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AddressAlreadyInUseException(SR.GetString(SR.SharedManagerBase, serviceName, SR.GetString(SR.SharedManagerFailedToListen))));
                        default: 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SharedManagerBase, serviceName, SR.GetString("SharedManager" + status))));
                    }
                }
            } 

            void HandleAllowDupHandlePermission(int myPid) 
            { 
                Debug.Print("SharedListenerProxy.HandleAllowDupHandlePermission() myPid: " + myPid);
                bool notNecessary = !OSEnvironmentHelper.IsVistaOrGreater && listenerUserSid.Equals(new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null)); 
                Debug.Print("SharedListenerProxy.HandleAllowDupHandlePermission() notNecessary(ServiceRunningAsLocalSystem): " + notNecessary);
                if (notNecessary)
                {
                    return; 
                }
 
                SecurityIdentifier myUserSid; 
                try
                { 
                    myUserSid = Utility.GetUserSidForPid(myPid);
                }
                catch (Win32Exception exception)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SharedManagerBase, serviceName, SR.GetString(SR.SharedManagerCurrentUserSidLookupFailure, exception.NativeErrorCode)), exception));
                } 
 
                Debug.Print("SharedListenerProxy.HandleAllowDupHandlePermission() myPid: " + myPid + " myUserSid: " + myUserSid.Value);
                notNecessary = !OSEnvironmentHelper.IsVistaOrGreater && myUserSid.Equals(listenerUserSid); 
                Debug.Print("SharedListenerProxy.HandleAllowDupHandlePermission() notNecessary(RunningUnderTheSameAccount): " + notNecessary);
                if (notNecessary)
                {
                    return; 
                }
 
                try 
                {
                    allowContext = AllowHelper.TryAllow(listenerUniqueSid.Value); 
                }
                catch (Win32Exception exception)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SharedManagerBase, 
                        serviceName, SR.GetString(SR.SharedManagerAllowDupHandleFailed, listenerUniqueSid.Value)), exception));
                } 
 
                if (DiagnosticUtility.ShouldTraceInformation)
                { 
                    DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.PortSharingDupHandleGranted,
                        SR.GetString(SR.TraceCodePortSharingDupHandleGranted, serviceName, listenerUniqueSid.Value), null, null);
                }
            } 

            IConnection BuildDuplicatedNamedPipeConnection(NamedPipeDuplicateContext duplicateContext, int connectionBufferSize) 
            { 
                if (DiagnosticUtility.ShouldTraceVerbose)
                { 
                    TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.PortSharingDuplicatedPipe, SR.GetString(SR.TraceCodePortSharingDuplicatedPipe));
                }

                PipeHandle duplicated = new PipeHandle(duplicateContext.Handle); 
                PipeConnection pipeConnection = new PipeConnection(duplicated, connectionBufferSize, false, true);
 
                return new NamedPipeValidatingConnection(new PreReadConnection(pipeConnection, duplicateContext.ReadData), 
                    this);
            } 

            IConnection BuildDuplicatedTcpConnection(TcpDuplicateContext duplicateContext, int connectionBufferSize)
            {
                if (DiagnosticUtility.ShouldTraceVerbose) 
                {
                    TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.PortSharingDuplicatedSocket, 
                        SR.GetString(SR.TraceCodePortSharingDuplicatedSocket)); 
                }
 
                Socket socket = new Socket(duplicateContext.SocketInformation);
                SocketConnection socketConnection = new SocketConnection(socket, connectionBufferSize, true);

                return new TcpValidatingConnection(new PreReadConnection(socketConnection, duplicateContext.ReadData), 
                    this);
            } 
 
            bool ValidateUriRoute(Uri uri, IPAddress address, int port)
            { 
                try
                {
                    // Synchronize with Unregister.
                    lock (ThisLock) 
                    {
                        if (closed) 
                        { 
                            return false;
                        } 

                        return ((IConnectionRegister)controlSessionWithListener).ValidateUriRoute(uri, address, port);
                    }
                } 
                catch (Exception exception)
                { 
                    if (DiagnosticUtility.ShouldTraceError) 
                    {
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Error); 
                    }

                    if (exception is CommunicationException ||
                        exception is TimeoutException) 
                    {
                        return false; 
                    } 

                    throw; 
                }
            }

            class NamedPipeValidatingConnection : DelegatingConnection 
            {
                SharedListenerProxy listenerProxy; 
                bool initialValidation; 

                public NamedPipeValidatingConnection(IConnection connection, SharedListenerProxy listenerProxy) 
                    : base(connection)
                {
                    this.listenerProxy = listenerProxy;
                    this.initialValidation = true; 
                }
 
                public override bool Validate(Uri uri) 
                {
                    if (this.initialValidation) // optimization for first usage 
                    {
                        this.initialValidation = false;
                        return true;
                    } 

                    return this.listenerProxy.ValidateUriRoute(uri, null, -1); 
                } 
            }
 
            class TcpValidatingConnection : DelegatingConnection
            {
                IPAddress ipAddress;
                int port; 
                SharedListenerProxy listenerProxy;
                bool initialValidation; 
 
                public TcpValidatingConnection(IConnection connection, SharedListenerProxy listenerProxy)
                    : base(connection) 
                {
                    this.listenerProxy = listenerProxy;

                    Socket socket = (Socket)connection.GetCoreTransport(); 
                    this.ipAddress = ((IPEndPoint)socket.LocalEndPoint).Address;
                    this.port = ((IPEndPoint)socket.LocalEndPoint).Port; 
                    this.initialValidation = true; 
                }
 
                public override bool Validate(Uri uri)
                {
                    if (this.initialValidation) // optimization for first usage
                    { 
                        this.initialValidation = false;
                        return true; 
                    } 

                    return this.listenerProxy.ValidateUriRoute(uri, ipAddress, port); 
                }
            }

            bool ReadEndpoint(string sharedMemoryName, out string listenerEndpoint) 
            {
                try 
                { 
                    if (SharedMemory.Read(sharedMemoryName, out listenerEndpoint))
                    { 
                        return true;
                    }

                    if (DiagnosticUtility.ShouldTraceInformation) 
                    {
                        DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.SharedManagerServiceEndpointNotExist, 
                            SR.GetString(SR.TraceCodeSharedManagerServiceEndpointNotExist, serviceName), null, null); 
                    }
 
                    return false;
                }
                catch (Win32Exception exception)
                { 
                    // Wrap unexpected Win32Exception.
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WrapEndpointReadingException(exception)); 
                } 
            }
 
            Exception WrapEndpointReadingException(Win32Exception exception)
            {
                string message;
                if (exception.NativeErrorCode == UnsafeNativeMethods.ERROR_FILE_NOT_FOUND) 
                {
                    message = SR.GetString(SR.SharedEndpointReadNotFound, this.baseAddress.BaseAddress.ToString(), 
                        this.serviceName); 
                }
                else if (exception.NativeErrorCode == UnsafeNativeMethods.ERROR_ACCESS_DENIED) 
                {
                    message = SR.GetString(SR.SharedEndpointReadDenied, this.baseAddress.BaseAddress.ToString());
                }
                else 
                {
                    message = SR.GetString(SR.SharedManagerBase, 
                        serviceName, SR.GetString(SR.SharedManagerServiceEndpointReadFailure, exception.NativeErrorCode)); 
                }
 
                return new CommunicationException(message, exception);
            }

            string HandleServiceStart(bool isReconnecting) 
            {
                string listenerEndpoint = null; 
                string sharedMemoryName = isTcp ? ListenerConstants.TcpSharedMemoryName : ListenerConstants.NamedPipeSharedMemoryName; 
                serviceName = SharedConnectionListener.GetServiceName(isTcp);
 
                // Try to read the endpoint only if not reconnecting.
                if (!isReconnecting)
                {
                    if (ReadEndpoint(sharedMemoryName, out listenerEndpoint)) 
                    {
                        return listenerEndpoint; 
                    } 
                }
 
                ServiceController service = new ServiceController(serviceName);
                try
                {
                    ServiceControllerStatus serviceStatus = service.Status; 
                    Debug.Print("ListenerServiceHelper.HandleServiceStart() service serviceName: " + serviceName + " is in status serviceStatus: " + serviceStatus);
                    if (isReconnecting) 
                    { 
                        if (serviceStatus == ServiceControllerStatus.Running)
                        { 
                            try
                            {
                                string listenerEndPoint = SharedMemory.Read(sharedMemoryName);
                                if (this.listenerEndPoint != listenerEndPoint) 
                                {
                                    // Service restarted. 
                                    return listenerEndPoint; 
                                }
                            } 
                            catch (Win32Exception exception)
                            {
                                Debug.Print("ListenerServiceHelper.HandleServiceStart() failed when reading the shared memory sharedMemoryName: " + sharedMemoryName + " exception: " + exception);
                                if (DiagnosticUtility.ShouldTraceWarning) 
                                {
                                    DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Warning); 
                                } 
                            }
 
                            // Wait for the service to exit the running state
                            serviceStatus = ExitServiceStatus(service, 50, 50, ServiceControllerStatus.Running);
                        }
                    } 

                    if (serviceStatus != ServiceControllerStatus.Running) 
                    { 
                        if (!isReconnecting)
                        { 
                            try
                            {
                                service.Start();
                            } 
                            catch (InvalidOperationException exception)
                            { 
                                Win32Exception win32Exception = exception.InnerException as Win32Exception; 
                                if (win32Exception != null)
                                { 
                                    if (win32Exception.NativeErrorCode == UnsafeNativeMethods.ERROR_SERVICE_DISABLED)
                                    {
                                        // service is disabled in the SCM, be specific
                                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SharedManagerBase, serviceName, SR.GetString(SR.SharedManagerServiceStartFailureDisabled, serviceName)), exception)); 
                                    }
                                    else if (win32Exception.NativeErrorCode != UnsafeNativeMethods.ERROR_SERVICE_ALREADY_RUNNING) 
                                    { 
                                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SharedManagerBase, serviceName, SR.GetString(SR.SharedManagerServiceStartFailure, win32Exception.NativeErrorCode)), exception));
                                    } 
                                }
                                else
                                {
                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SharedManagerBase, serviceName, SR.GetString(SR.SharedManagerServiceStartFailureNoError)), exception)); 
                                }
                            } 
                        } 
                        else if (serviceStatus != ServiceControllerStatus.StartPending)
                        { 
                            if (serviceStatus == ServiceControllerStatus.StopPending)
                            {
                                serviceStatus = ExitServiceStatus(service, 50, 1000, serviceStatus);
                            } 
                            if (serviceStatus == ServiceControllerStatus.Stopped)
                            { 
                                serviceStatus = ExitServiceStatus(service, 50, 1000, serviceStatus); 
                            }
                        } 

                        service.Refresh();
                        serviceStatus = service.Status;
                        Debug.Print("ListenerServiceHelper.HandleServiceStart() service serviceName: " + serviceName + " is in status serviceStatus: " + serviceStatus); 
                        if (serviceStatus == ServiceControllerStatus.StartPending)
                        { 
                            serviceStatus = ExitServiceStatus(service, 50, 50, ServiceControllerStatus.StartPending); 
                        }
                    } 

                    Debug.Print("ListenerServiceHelper.HandleServiceStart() final, service serviceName: " + serviceName + " is in status serviceStatus: " + serviceStatus);
                    if (serviceStatus != ServiceControllerStatus.Running)
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(
                            SR.SharedManagerBase, serviceName, SR.GetString(SR.SharedManagerServiceStartFailureNoError)))); 
                    } 
                }
                finally 
                {
                    service.Close();
                }
 
                try
                { 
                    return SharedMemory.Read(sharedMemoryName); 
                }
                catch (Win32Exception exception) 
                {
                    Debug.Print("ListenerServiceHelper.HandleServiceStart() final, failed when reading the shared memory sharedMemoryName: " + sharedMemoryName + " exception: " + exception);
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WrapEndpointReadingException(exception));
                } 
            }
 
            ServiceControllerStatus ExitServiceStatus(ServiceController service, int pollMin, int pollMax, ServiceControllerStatus status) 
            {
                Debug.Print("ListenerServiceHelper.ExitServiceStatus() pollMin: " + pollMin + " pollMax: " + pollMax + " exit serviceStatus: " + status); 
                int poll = pollMin;
                BackoffTimeoutHelper backoffHelper =
                    new BackoffTimeoutHelper(TimeSpan.MaxValue, TimeSpan.FromMilliseconds(pollMax), TimeSpan.FromMilliseconds(pollMin));
                for (; ; ) 
                {
                    if (this.closed) 
                    { 
                        // Break from backoff
                        return service.Status; 
                    }

                    backoffHelper.WaitAndBackoff();
                    service.Refresh(); 
                    ServiceControllerStatus serviceStatus = service.Status;
                    if (serviceStatus != status) 
                    { 
                        return serviceStatus;
                    } 
                }
            }

            void SendFault(IConnection connection, string faultCode) 
            {
                try 
                { 
                    if (drainBuffer == null)
                    { 
                        drainBuffer = new byte[1024];
                    }

                    // return fault and close connection 
                    InitialServerConnectionReader.SendFault(connection, faultCode, drainBuffer,
                        ListenerConstants.SharedSendTimeout, ListenerConstants.SharedMaxDrainSize); 
                } 
                catch (Exception exception)
                { 
                    if (DiagnosticUtility.IsFatal(exception))
                    {
                        throw;
                    } 

                    if (DiagnosticUtility.ShouldTraceError) 
                    { 
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Error);
                    } 
                }
            }

            bool HandleOnVia(DuplicateContext duplicateContext) 
            {
                if (this.onDuplicatedViaCallback == null) 
                { 
                    return true;
                } 

                // This is synchronized so that only the first service initializes the transport manager etc.
                // Subsequent services are skipped here.
                lock (ThisLock) 
                {
                    if (this.onDuplicatedViaCallback == null) 
                    { 
                        return true;
                    } 

                    int connectionBufferSize;
                    if (this.onDuplicatedViaCallback != null)
                    { 
                        try
                        { 
                            onDuplicatedViaCallback(duplicateContext.Via, out connectionBufferSize); 

                            // We completed the initialization. 
                            this.connectionBufferSize = connectionBufferSize;
                            this.onDuplicatedViaCallback = null;
                        }
                        catch (Exception e) 
                        {
                            if (DiagnosticUtility.ShouldTraceInformation) 
                            { 
                                DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                            } 

                            string faultCode = null;
                            if (e is ServiceActivationException)
                            { 
                                faultCode = FramingEncodingString.ServiceActivationFailedFault;
                            } 
                            else if (e is EndpointNotFoundException) 
                            {
                                faultCode = FramingEncodingString.EndpointNotFoundFault; 
                            }

                            IConnection connection = BuildConnectionFromData(duplicateContext, ConnectionOrientedTransportDefaults.ConnectionBufferSize);
                            if (faultCode != null) 
                            {
                                SendFault(connection, faultCode); 
                                return false; 
                            }
                            else 
                            {
                                connection.Abort();
                                if (e is CommunicationObjectAbortedException)
                                { 
                                    return false;
                                } 
 
                                throw;
                            } 
                        }
                    }
                }
 
                return true;
            } 
 
            IConnection BuildConnectionFromData(DuplicateContext duplicateContext, int connectionBufferSize)
            { 
                if (isTcp)
                {
                    return BuildDuplicatedTcpConnection((TcpDuplicateContext)duplicateContext, connectionBufferSize);
                } 
                else
                { 
                    return BuildDuplicatedNamedPipeConnection((NamedPipeDuplicateContext)duplicateContext, connectionBufferSize); 
                }
            } 

            IAsyncResult IConnectionDuplicator.BeginDuplicate(DuplicateContext duplicateContext, AsyncCallback callback, object state)
            {
                try 
                {
                    DuplicateConnectionAsyncResult result; 
                    if (!HandleOnVia(duplicateContext)) 
                    {
                        return new DuplicateConnectionAsyncResult(callback, state); 
                    }

                    result = new DuplicateConnectionAsyncResult(BuildConnectionFromData(duplicateContext,
                        this.connectionBufferSize), callback, state); 

                    parent.OnConnectionAvailable(result); 
 
                    return result;
                } 
                catch (Exception exception)
                {
                    if (DiagnosticUtility.ShouldTraceError)
                    { 
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Error);
                    } 
 
                    throw;
                } 
            }

            void IConnectionDuplicator.EndDuplicate(IAsyncResult result)
            { 
                DuplicateConnectionAsyncResult.End(result);
            } 
 
            void IInputSessionShutdown.ChannelFaulted(IDuplexContextChannel channel)
            { 
                OnControlChannelShutdown();
            }

            void IInputSessionShutdown.DoneReceiving(IDuplexContextChannel channel) 
            {
                OnControlChannelShutdown(); 
            } 

            void OnControlChannelShutdown() 
            {
                if (this.listenerClosed || !this.opened)
                {
                    return; 
                }
 
                lock (ThisLock) 
                {
                    if (this.listenerClosed || !this.opened) 
                    {
                        return;
                    }
 
                    listenerClosed = true;
                } 
 
                // Only reconnect in non-activation case.
                this.parent.OnListenerFaulted(queueId == 0); 
            }

            class SharedListenerProxyBehavior : IEndpointBehavior
            { 
                SharedListenerProxy proxy;
 
                public SharedListenerProxyBehavior(SharedListenerProxy proxy) 
                {
                    this.proxy = proxy; 
                }

                public void Validate(ServiceEndpoint serviceEndpoint) { }
                public void AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParameters) { } 
                public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher) { }
 
                public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior) 
                {
                    behavior.DispatchRuntime.InputSessionShutdownHandlers.Add(this.proxy); 
                }
            }
        }
 
        class DuplicateConnectionAsyncResult : AsyncResult
        { 
            IConnection connection; 
            public DuplicateConnectionAsyncResult(IConnection connection, AsyncCallback callback, object state)
                : base(callback, state) 
            {
                this.connection = connection;
            }
 
            public DuplicateConnectionAsyncResult(AsyncCallback callback, object state)
                : base(callback, state) 
            { 
                this.Complete(true);
            } 

            public IConnection Connection
            {
                get 
                {
                    return this.connection; 
                } 
            }
 
            public void CompleteOperation()
            {
                Complete(false);
            } 

            public static void End(IAsyncResult result) 
            { 
                AsyncResult.End(result);
            } 
        }
    }

    class AllowHelper : MarshalByRefObject 
    {
        // this is the real instance in the default AppDomain, otherwise it's a proxy 
        static AllowHelper singleton; 
        static Dictionary processWideRefCount;
        static object thisLock = new object(); 
        static object ThisLock { get { return thisLock; } }

        public override object InitializeLifetimeService()
        { 
            return null;
        } 
 
        static void EnsureInitialized()
        { 
            if (singleton != null)
            {
                return;
            } 

            lock (ThisLock) 
            { 
                if (singleton != null)
                { 
                    return;
                }

                if (AppDomain.CurrentDomain.IsDefaultAppDomain()) 
                {
                    processWideRefCount = new Dictionary(); 
                    singleton = new AllowHelper(); 
                }
                else 
                {
                    Guid rclsid = new Guid("CB2F6723-AB3A-11D2-9C40-00C04FA30A3E");
                    Guid riid = new Guid("CB2F6722-AB3A-11D2-9C40-00C04FA30A3E");
                    ListenerUnsafeNativeMethods.ICorRuntimeHost corRuntimeHost; 

                    // this call returns S_FALSE when this call did not load the library 
                    // which must be our case since we're already in managed code 
                    const int S_FALSE = 1;
                    int hresult = ListenerUnsafeNativeMethods.CorBindToRuntimeEx(IntPtr.Zero, IntPtr.Zero, 0, ref rclsid, ref riid, out corRuntimeHost); 
                    DiagnosticUtility.DebugAssert(hresult == S_FALSE, "AllowHelper..ctor() CorBindToRuntimeEx failed");

                    object defaultDomainAsObject;
                    corRuntimeHost.GetDefaultDomain(out defaultDomainAsObject); 
                    AppDomain defaultDomain = (AppDomain)defaultDomainAsObject;
                    if (!defaultDomain.IsDefaultAppDomain()) 
                    { 
                        DiagnosticUtility.DebugAssert("AllowHelper..ctor() GetDefaultDomain did not return the default domain!");
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(true); 
                    }
                    singleton = defaultDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(AllowHelper).FullName) as AllowHelper;
                }
            } 
        }
 
        public static IDisposable TryAllow(string newSid) 
        {
            EnsureInitialized(); 
            singleton.TryAllowCore(newSid);
            return new RegistrationForAllow(singleton, newSid);
        }
 
        void TryAllowCore(string newSid)
        { 
            // In DefaultAppDomain, need to initialize. 
            EnsureInitialized();
 
            lock (ThisLock)
            {
                RegistrationRefCount registration;
                if (!processWideRefCount.TryGetValue(newSid, out registration)) 
                {
                    registration = new RegistrationRefCount(newSid); 
                } 

                registration.AddRef(); 
            }
        }

        void UndoAllow(string grantedSid) 
        {
            lock (ThisLock) 
            { 
                RegistrationRefCount registration = processWideRefCount[grantedSid];
                registration.RemoveRef(); 
            }
        }

        // This type is not thread-safe. The caller needs to provide synchronization mechanism. 
        class RegistrationRefCount
        { 
            int refCount; 
            string grantedSid;
 
            public RegistrationRefCount(string grantedSid)
            {
                this.grantedSid = grantedSid;
            } 

            public void AddRef() 
            { 
                if (refCount == 0)
                { 
                    Utility.AddRightGrantedToAccount(new SecurityIdentifier(grantedSid), ListenerUnsafeNativeMethods.PROCESS_DUP_HANDLE);
                    processWideRefCount.Add(grantedSid, this);
                }
 
                refCount++;
            } 
 
            public void RemoveRef()
            { 
                refCount--;
                if (refCount == 0)
                {
                    Utility.RemoveRightGrantedToAccount(new SecurityIdentifier(grantedSid), ListenerUnsafeNativeMethods.PROCESS_DUP_HANDLE); 
                    processWideRefCount.Remove(grantedSid);
                } 
            } 
        }
 
        class RegistrationForAllow : IDisposable
        {
            string grantedSid;
            AllowHelper singleton; 

            public RegistrationForAllow(AllowHelper singleton, string grantedSid) 
            { 
                this.singleton = singleton;
                this.grantedSid = grantedSid; 
            }

            void IDisposable.Dispose()
            { 
                singleton.UndoAllow(grantedSid);
            } 
        } 
    }
} 

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