/// <summary>
        /// Create a new thread to receive the data from remote host.
        /// </summary>
        /// <param name="packetQueueManager">Store all event packets generated in receiving loop.</param>
        /// <param name="decodePacketCallback">Callback of packet decode.</param>
        /// <param name="stream">The stream used to receive data.</param>
        /// <param name="bufferSize">Buffer size used in receiving data.</param>
        public RdpbcgrReceiveThread(
            object endPoint,
            QueueManager packetQueueManager,
            DecodePacketCallback decodePacketCallback,
            Stream stream,
            int bufferSize,
            RdpbcgrServer rdpbcgrServer)
        {
            if (packetQueueManager == null)
            {
                throw new ArgumentNullException("packetQueueManager");
            }

            if (decodePacketCallback == null)
            {
                throw new ArgumentNullException("decodePacketCallback");
            }

            // Initialize variable.
            this.endPointIdentity = endPoint;
            this.packetQueue = packetQueueManager;
            this.decoder = decodePacketCallback;
            this.receiveStream = stream;
            this.maxBufferSize = bufferSize;
            this.rdpbcgrServer = rdpbcgrServer;
            this.receivingThread = new Thread((new ThreadStart(ReceiveLoop)));
        }
        /// <summary>
        ///  Constructor. Initialize member variables.
        /// </summary>
        /// <param name="transportConfig">Provides the transport parameters.</param>
        /// <param name="decodePacketCallback">Callback of decoding packet.</param>
        /// <param name="certificate">X509 certificate.</param>
        public RdpbcgrServerTransportStack(
            RdpbcgrServer rdpbcgrServer,
            RdpcbgrServerTransportConfig transportConfig,
            DecodePacketCallback decodePacketCallback,
            X509Certificate2 certificate)
        {
            this.rdpbcgrServer = rdpbcgrServer;
            this.config = transportConfig;
            if (this.config == null)
            {
                throw new System.InvalidCastException("TcpServerTransport needs SocketTransportConfig.");
            }

            this.decoder = decodePacketCallback;
            this.packetQueue = new QueueManager();
            this.listenSock = new Socket(transportConfig.LocalIpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            this.streamType = transportConfig.StreamType;
            IPEndPoint endPoint = new IPEndPoint(config.LocalIpAddress, config.LocalIpPort);
            this.listenSock.Bind(endPoint);
            this.listenSock.Listen(config.MaxConnections);
            this.acceptThread = new Thread(new ThreadStart(AcceptLoop));
            this.receivingStreams = new Dictionary<Socket, RdpbcgrReceiveThread>();
            this.cert = certificate;
        }
        /// <summary>
        /// Release resources.
        /// </summary>
        /// <param name="disposing">If disposing equals true, Managed and unmanaged resources are disposed.
        /// if false, Only unmanaged resources can be disposed.</param>
        private void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                exitLoop = true;
                // If disposing equals true, dispose all managed and unmanaged resources.
                if (disposing)
                {
                    if (this.listenSock != null)
                    {
                        this.listenSock.Close();
                        this.listenSock = null;
                    }

                    lock (this.receivingStreams)
                    {
                        if (this.receivingStreams != null)
                        {
                            foreach (KeyValuePair<Socket, RdpbcgrReceiveThread> kvp in this.receivingStreams)
                            {
                                kvp.Key.Close();
                                kvp.Value.Dispose();
                            }
                            this.receivingStreams = null;
                        }
                    }

                    if (this.packetQueue != null)
                    {
                        this.packetQueue.Dispose();
                        this.packetQueue = null;
                    }

                    if (this.acceptThread != null && this.acceptThread.ThreadState != ThreadState.Unstarted)
                    {
                        this.acceptThread.Join();
                    }
                }

                this.disposed = true;
            }
        }