/// <summary>
        /// Kills this connection
        /// </summary>
        /// <param name="softKill">If true will perform a shutdown before closing, otherwise close will happen with lingering disabled</param>
        public void Kill(bool softKill)
        {
            if (softKill)
            {
                // Soft close, do shutdown first
                IncomingConnection.Shutdown(SocketShutdown.Both);
            }
            else
            {
                // Hard close - force no lingering
                IncomingConnection.LingerState = new LingerOption(true, 0);
            }

            IncomingConnection.Dispose();
            OutgoingConnection.Dispose();
        }
        /// <summary>
        /// Handles the bidirectional data transfers
        /// </summary>
        private void _ProcessorHandler()
        {
            try
            {
                Server.Log("Connecting to {0}...", Server.RemoteEndpoint);
                Server.Log("Remote end point address family {0}", Server.RemoteEndpoint.AddressFamily);

                // Establish outgoing connection to the proxy
                OutgoingConnection = new Socket(Server.RemoteEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                Task connectTask = OutgoingConnection.ConnectAsync(Server.RemoteEndpoint.Address, Server.RemoteEndpoint.Port);
                connectTask.Wait(1000);

                // Writing connection information
                Server.Log("Connection established");

                // Obtain network streams
                NetworkStream outStream = new NetworkStream(OutgoingConnection, true);
                NetworkStream inStream  = new NetworkStream(IncomingConnection, true);

                // Ensure copying isn't paused
                Server.PermitCopying.Wait();

                // Tunnel the traffic between two connections
                while (IncomingConnection.Connected && OutgoingConnection.Connected && !Server.StopRequested)
                {
                    bool DataAvailable = false;

                    // Check incoming buffer
                    if (inStream.DataAvailable)
                    {
                        DataAvailable = true;
                        CopyData(inStream, "client", outStream, "server", Server.SimulatedInDelay);
                    }


                    // Check outgoing buffer
                    if (outStream.DataAvailable)
                    {
                        DataAvailable = true;
                        CopyData(outStream, "server", inStream, "client", Server.SimulatedOutDelay);
                    }

                    // Pause
                    if (DataAvailable)
                    {
                        // Poll the sockets
                        if ((IncomingConnection.Poll(100, SelectMode.SelectRead) && !inStream.DataAvailable) ||
                            (OutgoingConnection.Poll(100, SelectMode.SelectRead) && !outStream.DataAvailable))
                        {
                            break;
                        }

                        Thread.Sleep(10);
                    }
                    else
                    {
                        Thread.Sleep(1);
                    }

                    // Ensure copying isn't paused
                    Server.PermitCopying.Wait();
                }
            }
            catch (Exception ex)
            {
                Server.Log(ex.ToString());
            }

            try
            {
                // Disconnect the client
                IncomingConnection.Dispose();
                OutgoingConnection.Dispose();
            }
            catch (Exception) { }

            // Logging disconnection message
            Server.Log("Connection closed");

            // Notify parent
            Server.NotifyClientDisconnection(this);
        }