private static void DoHttpProcessing(TcpClient client)
        {
            Stream clientStream = client.GetStream();
            Stream outStream = clientStream; //use this stream for writing out - may change if we use ssl
            SslStream sslStream = null;
            StreamReader clientStreamReader = new StreamReader(clientStream);
            CacheEntry cacheEntry = null;
            MemoryStream cacheStream = null;

            if (Server.DumpHeaders || Server.DumpPostData || Server.DumpResponseData)
            {
                //make sure that things print out in order - NOTE: this is bad for performance
                Monitor.TryEnter(_outputLockObj, TimeSpan.FromMilliseconds(-1.0));
            }

            try
            {
                //read the first line HTTP command
                String httpCmd = clientStreamReader.ReadLine();
                if (String.IsNullOrEmpty(httpCmd))
                {
                    clientStreamReader.Close();
                    clientStream.Close();
                    return;
                }
                //break up the line into three components
                String[] splitBuffer = httpCmd.Split(spaceSplit, 3);

                String method = splitBuffer[0];
                String remoteUri = splitBuffer[1];
                Version version = new Version(1, 0);

                HttpWebRequest webReq;
                HttpWebResponse response = null;
                if (splitBuffer[0].ToUpper() == "CONNECT")
                {
                    //Browser wants to create a secure tunnel
                    //instead = we are going to perform a man in the middle "attack"
                    //the user's browser should warn them of the certification errors however.
                    //Please note: THIS IS ONLY FOR TESTING PURPOSES - you are responsible for the use of this code
                    remoteUri = "https://" + splitBuffer[1];
                    while (!String.IsNullOrEmpty(clientStreamReader.ReadLine())) ;
                    StreamWriter connectStreamWriter = new StreamWriter(clientStream);
                    connectStreamWriter.WriteLine("HTTP/1.0 200 Connection established");
                    connectStreamWriter.WriteLine(String.Format("Timestamp: {0}", DateTime.Now.ToString()));
                    connectStreamWriter.WriteLine("Proxy-agent: tb-proxy");
                    connectStreamWriter.WriteLine();
                    connectStreamWriter.Flush();

                    sslStream = new SslStream(clientStream, false);
                    try
                    {
                        sslStream.AuthenticateAsServer(_certificate, false, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, true);
                    }
                    catch (Exception)
                    {
                        sslStream.Close();
                        clientStreamReader.Close();
                        connectStreamWriter.Close();
                        clientStream.Close();
                        return;
                    }

                    //HTTPS server created - we can now decrypt the client's traffic
                    clientStream = sslStream;
                    clientStreamReader = new StreamReader(sslStream);
                    outStream = sslStream;
                    //read the new http command.
                    httpCmd = clientStreamReader.ReadLine();
                    if (String.IsNullOrEmpty(httpCmd))
                    {
                        clientStreamReader.Close();
                        clientStream.Close();
                        sslStream.Close();
                        return;
                    }
                    splitBuffer = httpCmd.Split(spaceSplit, 3);
                    method = splitBuffer[0];
                    remoteUri = remoteUri + splitBuffer[1];
                }

                //construct the web request that we are going to issue on behalf of the client.
                webReq = (HttpWebRequest)HttpWebRequest.Create(remoteUri);
                webReq.Method = method;
                webReq.ProtocolVersion = version;

                //read the request headers from the client and copy them to our request
                int contentLen = ReadRequestHeaders(clientStreamReader, webReq);

                webReq.Proxy = null;
                webReq.KeepAlive = false;
                webReq.AllowAutoRedirect = true;
                webReq.ProtocolVersion = HttpVersion.Version10;
                webReq.AutomaticDecompression = DecompressionMethods.None;

                if(Server.DumpHeaders)
                {
                    Console.WriteLine(String.Format("{0} {1} HTTP/{2}",webReq.Method,webReq.RequestUri.AbsoluteUri, webReq.ProtocolVersion));
                    DumpHeaderCollectionToConsole(webReq.Headers);
                }

                //using the completed request, check our cache
                if (method.ToUpper() == "GET")
                    cacheEntry = ProxyCache.GetData(webReq);
                else if (method.ToUpper() == "POST")
                {
                    char[] postBuffer = new char[contentLen];
                    int bytesRead;
                    int totalBytesRead = 0;
                    StreamWriter sw = new StreamWriter(webReq.GetRequestStream());
                    while (totalBytesRead < contentLen && (bytesRead = clientStreamReader.ReadBlock(postBuffer, 0, contentLen)) > 0)
                    {
                        totalBytesRead += bytesRead;
                        sw.Write(postBuffer, 0, bytesRead);
                        if (ProxyServer.Server.DumpPostData)
                            Console.Write(postBuffer, 0, bytesRead);
                    }
                    if (Server.DumpPostData)
                    {
                        Console.WriteLine();
                        Console.WriteLine();
                    }

                    sw.Close();
                }

                if (cacheEntry == null)
                {
                    //Console.WriteLine(String.Format("ThreadID: {2} Requesting {0} on behalf of client {1}", webReq.RequestUri, client.Client.RemoteEndPoint.ToString(), Thread.CurrentThread.ManagedThreadId));
                    webReq.Timeout = 15000;

                    try
                    {
                        response = (HttpWebResponse)webReq.GetResponse();
                    }
                    catch (WebException webEx)
                    {
                        response = webEx.Response as HttpWebResponse;
                    }
                    if (response != null)
                    {

                        // If TB Streamtags are requested
                        bool isTB = false;
                        string contentStr = "";
                        if (webReq.RequestUri.OriginalString.Contains("ChannelID=884") && webReq.RequestUri.OriginalString.Contains("Channel=TechnoBase"))
                        {
                            isTB = true; // yep
                            Console.WriteLine("[" + DateTime.Now.ToString("HH:mm:ss") + "] TechnoBase StreamTags requested"); // report to user

                            Random rnd = new Random(DateTime.Now.Millisecond);
                            TBParser tbp = new TBParser();
                            List<Track> trackList = tbp.getTracks();

                            string currentTimeStr = DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff");
                            StringBuilder sb = new StringBuilder(); // Build StreamTag Response
                            sb.Append("count=" + trackList.Count);
                            sb.Append("<br>");
                            sb.Append("vintern=1452");
                            sb.Append("<br>");
                            sb.Append("clistvintern=2160");
                            sb.Append("<br>");
                            sb.Append("time-ref=" + currentTimeStr);
                            sb.Append("<br>");
                            sb.Append("offset=01.01.1900 00:00:00");
                            sb.Append("<br>");
                            sb.Append("serverTime=" + currentTimeStr);
                            sb.Append("<br>");
                            sb.Append("FSListVIntern=100");
                            sb.Append("<br>");
                            sb.Append("ChargedListVIntern=103");
                            sb.Append("<br>");
                            sb.Append("rankingvintern=0");
                            sb.Append("<br>");
                            sb.Append("ResCode=0");
                            sb.Append("<br>");
                            sb.Append("ComTimeStamp=0");
                            sb.Append("<br>");
                            sb.Append("PeerFlag=0");
                            sb.Append("<br>");

                            foreach (Track trk in trackList)
                            {
                                if (trk.ID > 0)
                                {
                                    string songMD5 = GetMD5Hash(trk.ToString()); // Generate unique Track ID
                                    string songID9 = songMD5.Substring(0, 9);
                                    string songID6 = songMD5.Substring(0, 6);
                                    string songID4 = songMD5.Substring(0, 4);
                                    sb.Append("49127-12110 ");
                                    sb.Append(DateTime.Now.ToString("dd.MM.yyyy") + " "); // To be fixed (Incorrect date, might cause problems at 23:59 - 00:00)
                                    sb.Append(trk.TimeStart.ToString("HH:mm:ss.fff") + " "); // Time Start
                                    sb.Append(DateTime.Now.ToString("dd.MM.yyyy") + " "); // To be fixed (Incorrect date, might cause problems at 23:59 - 00:00)
                                    sb.Append(trk.TimeEnd.ToString("HH:mm:ss.fff") + " "); // Time End
                                    sb.Append("\"" + trk.Title + "\" "); // Title
                                    sb.Append("8 "); // 8 seems to work...
                                    sb.Append(songID9 + " "); // Song ID
                                    sb.Append("\"" + trk.Artist + "\" "); // Artist
                                    sb.Append("\"\" "); // Album
                                    sb.Append("\"\" "); // URL
                                    sb.Append("\"0\" "); // ?
                                    sb.Append("\"2000\" "); // Year
                                    sb.Append("\"\" "); // ?
                                    sb.Append("\"\" "); // ?
                                    sb.Append("\"\" "); // Shop URL
                                    sb.Append("5 "); // ?
                                    sb.Append(songID6 + " "); // Song ID
                                    sb.Append(songID4 + " "); // Song ID
                                    sb.Append("0 ");
                                    sb.Append("0 ");
                                    sb.Append("\"" + trk.CoverURL + "\" "); // Cover Image URL
                                    sb.Append(songID9 + " "); // Song ID
                                    sb.Append("<br>");

                                    // Example Response:
                                    // 49127-12110 01.11.2012 17:24:33.393 01.11.2012 17:29:34.307 "Everything" 5 331039793 "Safri Duo" "Episode II" "http://www.safriduo.dk/" "151" "2001" "" "http://www.amazon.de/Episode-II-Safri-Duo/dp/B00005KKA5/ref=sr_1_2?ie=UTF8&s=music&qid=1216825657&sr=8-2" "http://www.amazon.de/Episode-II-Safri-Duo/dp/B00005KKA5/ref=sr_1_2?ie=UTF8&s=music&qid=1216825657&sr=8-2" 4 1083354 5870,5 0 0 "http://ecx.images-amazon.com/images/I/41W4SZVXERL._SX240_.jpg" "112545908757223"
                                }
                            }

                            contentStr = sb.ToString();
                        }

                        List<Tuple<String, String>> responseHeaders = ProcessResponse(response, contentStr.Length);
                        StreamWriter myResponseWriter = new StreamWriter(outStream);
                        Stream responseStream = response.GetResponseStream();

                        try
                        {
                            //send the response status and response headers
                            WriteResponseStatus(response.StatusCode, response.StatusDescription, myResponseWriter);
                            WriteResponseHeaders(myResponseWriter, responseHeaders);

                            DateTime? expires = null;
                            CacheEntry entry = null;
                            Boolean canCache = (sslStream == null && ProxyCache.CanCache(response.Headers, ref expires));
                            if (canCache)
                            {
                                entry = ProxyCache.MakeEntry(webReq, response,responseHeaders, expires);
                                if (response.ContentLength > 0)
                                    cacheStream = new MemoryStream(entry.ResponseBytes);
                            }

                            Byte[] buffer;
                            if (isTB)
                            {
                                buffer = Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding("iso-8859-1"), Encoding.UTF8.GetBytes(contentStr));
                            }
                            else
                            {
                                if (response.ContentLength > 0)
                                    buffer = new Byte[response.ContentLength];
                                else
                                    buffer = new Byte[BUFFER_SIZE];
                            }

                            int bytesRead;

                            if (isTB)
                            {
                                //myResponseWriter.WriteLine(contentStr);
                                outStream.Write(buffer, 0, buffer.Length);
                            }
                            else{
                                while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0)
                                {
                                    if (cacheStream != null)
                                        cacheStream.Write(buffer, 0, bytesRead);
                                    outStream.Write(buffer, 0, bytesRead);
                                    //Console.WriteLine(bytesRead);
                                    if (Server.DumpResponseData)
                                        Console.Write(UTF8Encoding.UTF8.GetString(buffer, 0, bytesRead));
                                }
                            }

                            if (Server.DumpResponseData)
                            {
                                Console.WriteLine();
                                Console.WriteLine();
                            }

                            responseStream.Close();
                            if (cacheStream != null)
                            {
                                cacheStream.Flush();
                                cacheStream.Close();
                            }

                            outStream.Flush();
                            if (canCache)
                                ProxyCache.AddData(entry);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                        finally
                        {
                            responseStream.Close();
                            response.Close();
                            myResponseWriter.Close();
                        }
                    }
                }
                else
                {
                    //serve from cache
                    StreamWriter myResponseWriter = new StreamWriter(outStream);
                    try
                    {
                        WriteResponseStatus(cacheEntry.StatusCode, cacheEntry.StatusDescription, myResponseWriter);
                        WriteResponseHeaders(myResponseWriter, cacheEntry.Headers);
                        if (cacheEntry.ResponseBytes != null)
                        {
                            outStream.Write(cacheEntry.ResponseBytes, 0, cacheEntry.ResponseBytes.Length);
                            if (ProxyServer.Server.DumpResponseData)
                                Console.Write(UTF8Encoding.UTF8.GetString(cacheEntry.ResponseBytes));
                        }
                        myResponseWriter.Close();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                    finally
                    {
                        myResponseWriter.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                if (Server.DumpHeaders || Server.DumpPostData || Server.DumpResponseData)
                {
                    //release the lock
                    Monitor.Exit(_outputLockObj);
                }

                clientStreamReader.Close();
                clientStream.Close();
                if (sslStream != null)
                    sslStream.Close();
                outStream.Close();
                if (cacheStream != null)
                    cacheStream.Close();
            }
        }
        public void ThreadHandleClient(object o)
        {
            try
            {
                Socket client = (Socket)o;
                Debug.Print("lingerstate=" + client.LingerState.Enabled.ToString() + " timeout=" + client.LingerState.LingerTime.ToString());
                NetworkStream ns = new NetworkStream(client);
                //RECEIVE CLIENT DATA
                byte[] buffer = new byte[2048];
                int rec = 0, sent = 0, transferred = 0, rport = 0;
                string data = "";
                do
                {
                    rec = ns.Read(buffer, 0, buffer.Length);
                    data += Encoding.ASCII.GetString(buffer, 0, rec);
                } while (rec == buffer.Length);

                //PARSE DESTINATION AND SEND REQUEST
                string line = data.Replace("\r\n", "\n").Split(new string[] { "\n" }, StringSplitOptions.None)[0];
                Uri uri = new Uri(line.Split(new string[] { " " }, StringSplitOptions.None)[1]);
                Debug.Print("CLIENT REQUEST RECEIVED: " + uri.OriginalString);
                if (uri.Scheme == "https")
                {
                    rport = 443;
                    Debug.Print("HTTPS - 443");
                }
                else
                {
                    rport = 80;
                    Debug.Print("HTTP - 443");
                }

                string tbResponse = "";

                if (uri.OriginalString.Contains("ChannelID=884") && uri.OriginalString.Contains("Channel=TechnoBase"))
                {
                    isTechnobase = true;
                    Random rnd = new Random(DateTime.Now.Millisecond);
                    TBParser tbp = new TBParser();
                    List<Track> trackList = tbp.getTracks();

                    string currentTimeStr = DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff");
                    StringBuilder sb = new StringBuilder();
                    sb.Append("count=" + trackList.Count);
                    sb.Append("<br>");
                    sb.Append("vintern=1452");
                    sb.Append("<br>");
                    sb.Append("clistvintern=2160");
                    sb.Append("<br>");
                    sb.Append("time-ref=" + currentTimeStr);
                    sb.Append("<br>");
                    sb.Append("offset=01.01.1900 00:00:00");
                    sb.Append("<br>");
                    sb.Append("serverTime=" + currentTimeStr);
                    sb.Append("<br>");
                    sb.Append("FSListVIntern=100");
                    sb.Append("<br>");
                    sb.Append("ChargedListVIntern=103");
                    sb.Append("<br>");
                    sb.Append("rankingvintern=0");
                    sb.Append("<br>");
                    sb.Append("ResCode=0");
                    sb.Append("<br>");
                    sb.Append("ComTimeStamp=0");
                    sb.Append("<br>");
                    sb.Append("PeerFlag=0");
                    sb.Append("<br>");

                    foreach (Track trk in trackList)
                    {
                        if (trk.ID > 0)
                        {
                            sb.Append("49127-12110 ");
                            sb.Append(DateTime.Now.ToString("dd.MM.yyyy") + " "); // To be fixed (Incorrect date)
                            sb.Append(trk.TimeStart.ToString("HH:mm:ss.fff") + " "); // Time Start
                            sb.Append(DateTime.Now.ToString("dd.MM.yyyy") + " "); // To be fixed (Incorrect date)
                            sb.Append(trk.TimeEnd.ToString("HH:mm:ss.fff") + " "); // Time End
                            sb.Append("\"" + trk.Title + "\" "); // Title
                            sb.Append(rnd.Next(1, 10) + " "); // ?
                            sb.Append(rnd.Next(100000000, 999999999) + " "); // ?
                            sb.Append("\"" + trk.Artist + "\" "); // Artist
                            sb.Append("\"\" "); // Album
                            sb.Append("\"\" "); // URL
                            sb.Append("\"0\" "); // ?
                            sb.Append("\"2000\" "); // Year
                            sb.Append("\"\" "); // ?
                            sb.Append("\"\" "); // ?
                            sb.Append("\"\" "); // Shop URL
                            sb.Append(rnd.Next(1, 10) + " ");
                            sb.Append(rnd.Next(100000, 999999) + " ");
                            sb.Append(rnd.Next(1000, 9999) + " ");
                            sb.Append("0 ");
                            sb.Append("0 ");
                            sb.Append("\"" + trk.CoverURL + "\" "); // Cover Image URL
                            sb.Append("\"" + rnd.Next(100000000, 999999999) + "\""); //195048320234
                            sb.Append("<br>");
                            //49127-12110 01.11.2012 17:24:33.393 01.11.2012 17:29:34.307 "Everything" 5 331039793 "Safri Duo" "Episode II" "http://www.safriduo.dk/" "151" "2001" "" "http://www.amazon.de/Episode-II-Safri-Duo/dp/B00005KKA5/ref=sr_1_2?ie=UTF8&s=music&qid=1216825657&sr=8-2" "http://www.amazon.de/Episode-II-Safri-Duo/dp/B00005KKA5/ref=sr_1_2?ie=UTF8&s=music&qid=1216825657&sr=8-2" 4 1083354 5870,5 0 0 "http://ecx.images-amazon.com/images/I/41W4SZVXERL._SX240_.jpg" "112545908757223"
                        }
                    }

                    string contentStr = sb.ToString();
                    StringBuilder hsb = new StringBuilder();

                    hsb.AppendLine("HTTP/1.1 200 OK");
                    hsb.AppendLine("Cache-Control: private");
                    hsb.AppendLine("Content-Type: text/html; charset=Windows-1252");
                    hsb.AppendLine("Server: Microsoft-IIS/7.5");
                    hsb.AppendLine("X-AspNet-Version: 4.0.30319");
                    hsb.AppendLine("X-Powered-By: ASP.NET");
                    hsb.AppendLine("Date: Thu, 01 Nov 2012 20:11:43 GMT");
                    hsb.AppendLine("Content-Length: " + contentStr.Length);
                    hsb.AppendLine("");
                    hsb.AppendLine(contentStr);

                    tbResponse = hsb.ToString();
                    Debug.WriteLine(tbResponse);
                }

                IPHostEntry rh = Dns.GetHostEntry(uri.Host);
                Socket webserver = new Socket(rh.AddressList[0].AddressFamily, SocketType.Stream, ProtocolType.IP);
                webserver.Connect(new IPEndPoint(rh.AddressList[0], rport));
                byte[] databytes = Encoding.ASCII.GetBytes(data);
                webserver.Send(databytes, databytes.Length, SocketFlags.None);
                Debug.Print("SENT TO SERVER. WILL NOW RELAY: " + data);

                //START RELAY
                buffer = new byte[2048];
                bool firstTime = true;
                rec = 0;
                data = "";
                do
                {
                    transferred = 0;
                    if (isTechnobase)
                    {
                        sent = client.Send(StrToByteArray(tbResponse), SocketFlags.None);
                    }
                    else
                    {
                        do
                        {
                            if (webserver.Poll((firstTime ? 9000 : 2000) * 1000, SelectMode.SelectRead))
                            {
                                rec = webserver.Receive(buffer, buffer.Length, SocketFlags.None);
                                //Debug.Print("RECEIVED FROM WEBSERVER[" + rec.ToString() + "]: " + Encoding.ASCII.GetString(buffer, 0, rec));
                                firstTime = false;
                                sent = client.Send(buffer, rec, SocketFlags.None);
                                //Debug.Print("SENT TO CLIENT[" + sent.ToString() + "]: " + Encoding.ASCII.GetString(buffer, 0, rec));
                                transferred += rec;
                            }
                            else
                            {
                                Debug.Print("No data polled from webserver");
                            }
                        } while (rec == buffer.Length);

                        Debug.Print("loop-1 finished");
                    }
                    //if (transferred == 0)
                    //     break;

                    //transferred = 0;
                    //rec = 0;
                    //do
                    //{
                    //    if (client.Poll(1000 * 1000, SelectMode.SelectRead))
                    //    {
                    //        rec = client.Receive(buffer, buffer.Length, SocketFlags.None);
                    //        Debug.Print("RECEIVED FROM CLIENT: " + Encoding.ASCII.GetString(buffer, 0, rec));

                    //        sent = webserver.Send(buffer, rec, SocketFlags.None);
                    //        Debug.Print("SENT TO WEBSERVER[" + sent.ToString() + "]: " + Encoding.ASCII.GetString(buffer, 0, rec));
                    //        transferred += rec;
                    //    }
                    //    else
                    //    {
                    //        Debug.Print("No data polled from client");
                    //    }
                    //} while (rec == buffer.Length);
                    //Debug.Print("loop-2 finished");

                } while (transferred > 0);
                Debug.Print("LOOP ENDS. EXITING THREAD");
                client.Close();
                webserver.Close();
            }
            catch (Exception ex)
            {
                Debug.Print("Error occured: " + ex.Message);
            }
            finally
            {
                Debug.Print("Client thread closed");
            }
        }