private void ProcessIntegratedSecurityAuthentication(IAsyncResult asyncResult)
        {
            Tuple<TransportProvider<TlsSocket>, NegotiateStream> state = (Tuple<TransportProvider<TlsSocket>, NegotiateStream>)asyncResult.AsyncState;
            TransportProvider<TlsSocket> client = state.Item1;
            IPEndPoint remoteEndPoint = client.Provider.Socket.RemoteEndPoint as IPEndPoint;
            NegotiateStream negotiateStream = state.Item2;
            WindowsPrincipal clientPrincipal = null;

            try
            {
                try
                {
                    negotiateStream.EndAuthenticateAsServer(asyncResult);

                    if (negotiateStream.RemoteIdentity is WindowsIdentity)
                        clientPrincipal = new WindowsPrincipal((WindowsIdentity)negotiateStream.RemoteIdentity);
                }
                catch (InvalidCredentialException)
                {
                    if (!m_ignoreInvalidCredentials)
                        throw;
                }

                TlsClientInfo clientInfo = new TlsClientInfo
                {
                    Client = client,
                    SendLock = new object(),
                    SendQueue = new ConcurrentQueue<TlsServerPayload>(),
                    ClientPrincipal = clientPrincipal
                };

                // Create operation to dump send queue payloads when the queue grows too large.
                clientInfo.DumpPayloadsOperation = new ShortSynchronizedOperation(() =>
                {
                    TlsServerPayload payload;

                    // Check to see if the client has reached the maximum send queue size.
                    if (m_maxSendQueueSize > 0 && clientInfo.SendQueue.Count >= m_maxSendQueueSize)
                    {
                        for (int i = 0; i < m_maxSendQueueSize; i++)
                        {
                            if (clientInfo.SendQueue.TryDequeue(out payload))
                            {
                                payload.WaitHandle.Set();
                                payload.WaitHandle.Dispose();
                                payload.WaitHandle = null;
                            }
                        }

                        throw new InvalidOperationException($"Client {clientInfo.Client.ID} connected to TCP server reached maximum send queue size. {m_maxSendQueueSize} payloads dumped from the queue.");
                    }
                }, ex => OnSendClientDataException(clientInfo.Client.ID, ex));

                // We can proceed further with receiving data from the client.
                m_clientInfoLookup.TryAdd(client.ID, clientInfo);

                OnClientConnected(client.ID);
                ReceivePayloadAsync(client);
            }
            catch (Exception ex)
            {
                // Notify of the exception.
                if ((object)remoteEndPoint != null)
                {
                    string clientAddress = remoteEndPoint.Address.ToString();
                    string errorMessage = $"Unable to authenticate connection to client [{clientAddress}]: {ex.Message}";
                    OnClientConnectingException(new Exception(errorMessage, ex));
                }
                TerminateConnection(client, false);
            }
            finally
            {
                negotiateStream.Dispose();
            }
        }
        /// <summary>
        /// Callback method for asynchronous authenticate operation.
        /// </summary>
        private void ProcessTlsAuthentication(IAsyncResult asyncResult)
        {
            TransportProvider<TlsSocket> client = (TransportProvider<TlsSocket>)asyncResult.AsyncState;
            IPEndPoint remoteEndPoint = client.Provider.Socket.RemoteEndPoint as IPEndPoint;
            SslStream stream = client.Provider.SslStream;

            try
            {
                stream.EndAuthenticateAsServer(asyncResult);

                if (EnabledSslProtocols != SslProtocols.None)
                {
                    if (!stream.IsAuthenticated)
                        throw new InvalidOperationException("Unable to authenticate.");

                    if (!stream.IsEncrypted)
                        throw new InvalidOperationException("Unable to encrypt data stream.");
                }

                if (m_integratedSecurity)
                {
#if !MONO
                    NegotiateStream negotiateStream = new NegotiateStream(stream, true);
                    negotiateStream.BeginAuthenticateAsServer(ProcessIntegratedSecurityAuthentication, Tuple.Create(client, negotiateStream));
#endif
                }
                else
                {
                    TlsClientInfo clientInfo = new TlsClientInfo
                    {
                        Client = client,
                        SendLock = new object(),
                        SendQueue = new ConcurrentQueue<TlsServerPayload>()
                    };

                    // Create operation to dump send queue payloads when the queue grows too large.
                    clientInfo.DumpPayloadsOperation = new ShortSynchronizedOperation(() =>
                    {
                        TlsServerPayload payload;

                        // Check to see if the client has reached the maximum send queue size.
                        if (m_maxSendQueueSize > 0 && clientInfo.SendQueue.Count >= m_maxSendQueueSize)
                        {
                            for (int i = 0; i < m_maxSendQueueSize; i++)
                            {
                                if (clientInfo.SendQueue.TryDequeue(out payload))
                                {
                                    payload.WaitHandle.Set();
                                    payload.WaitHandle.Dispose();
                                    payload.WaitHandle = null;
                                }
                            }

                            throw new InvalidOperationException($"Client {clientInfo.Client.ID} connected to TCP server reached maximum send queue size. {m_maxSendQueueSize} payloads dumped from the queue.");
                        }
                    }, ex => OnSendClientDataException(clientInfo.Client.ID, ex));

                    // We can proceed further with receiving data from the client.
                    m_clientInfoLookup.TryAdd(client.ID, clientInfo);

                    OnClientConnected(client.ID);
                    ReceivePayloadAsync(client);
                }
            }
            catch (Exception ex)
            {
                // Notify of the exception.
                if ((object)remoteEndPoint != null)
                {
                    string clientAddress = remoteEndPoint.Address.ToString();
                    string errorMessage = $"Unable to authenticate connection to client [{clientAddress}]: {CertificateChecker.ReasonForFailure ?? ex.Message}";
                    OnClientConnectingException(new Exception(errorMessage, ex));
                }
                TerminateConnection(client, false);
            }
        }