/// <summary>
        /// constructor
        /// </summary>
        /// <param name="tcpListener">
        /// a TcpListener that specifies the listener.
        /// </param>
        /// <param name="tcpServerTransport">
        /// a TcpServerTransport that represents the owner of listener.
        /// </param>
        /// <param name="isLspHooked">
        /// a bool value that indicates whether lsp hooked the transport.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// thrown when tcpListener is null.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when tcpServerTransport is null.
        /// </exception>
        public TcpServerListener(TcpListener tcpListener, TcpServerTransport tcpServerTransport, bool isLspHooked)
        {
            if (tcpListener == null)
            {
                throw new ArgumentNullException("tcpListener");
            }

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

            this.lspHooked = isLspHooked;
            this.listener = tcpListener;
            this.server = tcpServerTransport;
            this.thread = new ThreadManager(AcceptLoop, Unblock);
        }
        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="tcpClient">
        /// a TcpClient object that specifies the tcp client.
        /// </param>
        /// <param name="tcpServerTransport">
        /// a TcpServerTransport that represents the owner of listener.
        /// </param>
        /// <param name="lspHookedLocalEP">
        /// an IPEndPoint object that specifies the local endpoint.<para/>
        /// if LSP hooked, return the required local endpoint.<para/>
        /// otherwise, return the actual listened local endpoint.
        /// </param>
        /// <param name="isLspHooked">
        /// a bool value that indicates whether lsp hooked the transport.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// thrown when the tcpClient is null!
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when the tcpServerTransport is null!
        /// </exception>
        public TcpServerConnection(
            TcpClient tcpClient, TcpServerTransport tcpServerTransport, IPEndPoint lspHookedLocalEP, bool isLspHooked)
        {
            if (tcpClient == null)
            {
                throw new ArgumentNullException("tcpClient");
            }

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

            this.isAForwarderChannel = false;
            this.lspHooked = isLspHooked;
            this.stream = tcpClient.GetStream();
            this.server = tcpServerTransport;
            this.thread = new ThreadManager(TcpServerConnectionReceiveLoop, Unblock);
            this.buffer = new BytesBuffer();

            if (isLspHooked)
            {
                IPEndPoint destinationEndpoint;
                this.localEndPoint = lspHookedLocalEP;
                this.remoteEndPoint = LspConsole.Instance.RetrieveRemoteEndPoint(tcpClient.Client, out destinationEndpoint);

                //if equals, it means this is a forwarder channel.
                if (remoteEndPoint.Equals(destinationEndpoint))
                {
                    isAForwarderChannel = true;
                }
            }
            else
            {
                this.localEndPoint = tcpClient.Client.LocalEndPoint as IPEndPoint;
                this.remoteEndPoint = tcpClient.Client.RemoteEndPoint as IPEndPoint;
            }
        }