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"); } }