/**
         * This is the main method of each thread of HTTP processing.  We pass this method
         * to the thread constructor when starting a new connection.
         */
        public void process()
        {
            try
            {
                // Increment the number of current connections
                Interlocked.Increment(ref threads);
                // Bundle up our sockets nice and tight in various streams
                ns = new NetworkStream(s, FileAccess.ReadWrite);
                // It looks like these streams buffer
                sr = new StreamReader(ns);
                sw = new StreamWriter(ns);
                // Parse the request, if that succeeds, read the headers, if that
                // succeeds, then write the given URL to the stream, if possible.
                while (parseRequest())
                {
                    if (readHeaders())
                    {
                        if (method == "POST")
                        {
                            bool tmp = readBody();
                            //Console.WriteLine(tmp.ToString() + ": " + url + " - " + body);
                            if (tmp)
                            {
                                ParseParams(body, ref parameters);
                            }
                            else
                            {
                                writeError(400, "_FAILEDSEND_" + url + "_");
                                return;
                            }
                        }
                        // This makes sure we don't have too many persistent connections and also
                        // checks to see if the client can maintain keep-alive, if so then we will
                        // keep this http processor around to process again.
                        if (threads <= NUMSIMUL && "Keep-Alive".Equals(headers["Connection"]))
                        {
                            keepAlive = true;
                        }

                        DoResponse();

                        // If keep alive is not active then we want to close down the streams
                        // and shutdown the socket
                        if (!keepAlive)
                        {
                            ns.Close();
                            s.Shutdown(SocketShutdown.Both);
                            break;
                        }
                    }
                }
            }
            finally
            {
                // Always decrement the number of connections
                Interlocked.Decrement(ref threads);
                doCallback = null;
            }
        }
 /**
  * Each HTTP processor object handles one client.  If Keep-Alive is enabled then this
  * object will be reused for subsequent requests until the client breaks keep-alive.
  * This usually happens when it times out.  Because this could easily lead to a DoS
  * attack, we keep track of the number of open processors and only allow 100 to be
  * persistent active at any one time.  Additionally, we do not allow more than 500
  * outstanding requests.
  */
 public HttpProcessor(Socket s, HttpServer.httpCallback hcb)
 {
     this.s     = s;
     headers    = new Hashtable();
     doCallback = hcb;
 }