Commit 02be898e authored by justcoding121's avatar justcoding121 Committed by justcoding121

Fix memory leaks

parent f6dc0470
...@@ -6,7 +6,7 @@ using System.Security.Cryptography.X509Certificates; ...@@ -6,7 +6,7 @@ using System.Security.Cryptography.X509Certificates;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
public class CertificateManager public class CertificateManager : IDisposable
{ {
private const string CERT_CREATE_FORMAT = private const string CERT_CREATE_FORMAT =
"-ss {0} -n \"CN={1}, O={2}\" -sky {3} -cy {4} -m 120 -a sha256 -eku 1.3.6.1.5.5.7.3.1 -b {5:MM/dd/yyyy} {6}"; "-ss {0} -n \"CN={1}, O={2}\" -sky {3} -cy {4} -m 120 -a sha256 -eku 1.3.6.1.5.5.7.3.1 -b {5:MM/dd/yyyy} {6}";
...@@ -172,5 +172,14 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -172,5 +172,14 @@ namespace Titanium.Web.Proxy.Helpers
return certCreatArgs; return certCreatArgs;
} }
public void Dispose()
{
if (MyStore != null)
MyStore.Close();
if (RootStore != null)
RootStore.Close();
}
} }
} }
\ No newline at end of file
...@@ -44,9 +44,13 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -44,9 +44,13 @@ namespace Titanium.Web.Proxy.Helpers
return readBuffer.ToString(); return readBuffer.ToString();
} }
catch (IOException) catch (IOException)
{ return readBuffer.ToString(); } {
return readBuffer.ToString();
}
catch (Exception) catch (Exception)
{ throw; } {
throw;
}
} }
......
...@@ -9,20 +9,14 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -9,20 +9,14 @@ namespace Titanium.Web.Proxy.Helpers
public static class StreamHelper public static class StreamHelper
{ {
private const int DEFAULT_BUFFER_SIZE = 8192; // +32767 private const int DEFAULT_BUFFER_SIZE = 8192; // +32767
public static void CopyTo(this Stream input, Stream output)
{
input.CopyTo(output, DEFAULT_BUFFER_SIZE);
return;
}
public static void CopyTo(string initialData, Stream input, Stream output, int bufferSize) public static void CopyTo(string initialData, Stream input, Stream output, int bufferSize)
{ {
var bytes = Encoding.ASCII.GetBytes(initialData); var bytes = Encoding.ASCII.GetBytes(initialData);
output.Write(bytes,0, bytes.Length); output.Write(bytes,0, bytes.Length);
CopyTo(input, output, bufferSize); CopyTo(input, output, bufferSize);
} }
public static void CopyTo(this Stream input, Stream output, int bufferSize) public static void CopyTo(Stream input, Stream output, int bufferSize)
{ {
try try
{ {
......
...@@ -6,6 +6,7 @@ using System.Net.Security; ...@@ -6,6 +6,7 @@ using System.Net.Security;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Net.Sockets;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
...@@ -16,24 +17,38 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -16,24 +17,38 @@ namespace Titanium.Web.Proxy.Helpers
public static void SendRaw(string hostname, int tunnelPort, System.IO.Stream clientStream) public static void SendRaw(string hostname, int tunnelPort, System.IO.Stream clientStream)
{ {
System.Net.Sockets.TcpClient tunnelClient = null;
NetworkStream tunnelStream = null;
System.Net.Sockets.TcpClient tunnelClient = new System.Net.Sockets.TcpClient(hostname, tunnelPort); try
var tunnelStream = tunnelClient.GetStream(); {
var tunnelReadBuffer = new byte[BUFFER_SIZE]; tunnelClient = new System.Net.Sockets.TcpClient(hostname, tunnelPort);
tunnelStream = tunnelClient.GetStream();
var tunnelReadBuffer = new byte[BUFFER_SIZE];
Task sendRelay = new Task(() => StreamHelper.CopyTo(clientStream, tunnelStream, BUFFER_SIZE)); Task sendRelay = Task.Factory.StartNew(() => StreamHelper.CopyTo(clientStream, tunnelStream, BUFFER_SIZE));
Task receiveRelay = new Task(() => StreamHelper.CopyTo(tunnelStream, clientStream, BUFFER_SIZE)); Task receiveRelay = Task.Factory.StartNew(() => StreamHelper.CopyTo(tunnelStream, clientStream, BUFFER_SIZE));
sendRelay.Start(); sendRelay.Start();
receiveRelay.Start(); receiveRelay.Start();
Task.WaitAll(sendRelay, receiveRelay); Task.WaitAll(sendRelay, receiveRelay);
}
catch
{
if (tunnelStream != null)
{
tunnelStream.Close();
tunnelStream.Dispose();
}
if (tunnelStream != null) if (tunnelClient != null)
tunnelStream.Close(); tunnelClient.Close();
if (tunnelClient != null) throw;
tunnelClient.Close(); }
} }
public static void SendRaw(string httpCmd, string secureHostName, List<string> requestLines, bool isHttps, Stream clientStream) public static void SendRaw(string httpCmd, string secureHostName, List<string> requestLines, bool isHttps, Stream clientStream)
{ {
...@@ -76,30 +91,51 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -76,30 +91,51 @@ namespace Titanium.Web.Proxy.Helpers
} }
System.Net.Sockets.TcpClient tunnelClient = new System.Net.Sockets.TcpClient(hostname, tunnelPort); System.Net.Sockets.TcpClient tunnelClient = null;
var tunnelStream = tunnelClient.GetStream() as System.IO.Stream; Stream tunnelStream = null;
try
if (isHttps)
{ {
var sslStream = new SslStream(tunnelStream); tunnelClient = new System.Net.Sockets.TcpClient(hostname, tunnelPort);
sslStream.AuthenticateAsClient(hostname); tunnelStream = tunnelClient.GetStream() as Stream;
tunnelStream = sslStream;
}
if (isHttps)
{
SslStream sslStream = null;
try
{
sslStream = new SslStream(tunnelStream);
sslStream.AuthenticateAsClient(hostname);
tunnelStream = sslStream;
}
catch
{
if (sslStream != null)
sslStream.Dispose();
}
}
var sendRelay = new Task(() => StreamHelper.CopyTo(sb.ToString(), clientStream, tunnelStream, BUFFER_SIZE));
var receiveRelay = new Task(() => StreamHelper.CopyTo(tunnelStream, clientStream, BUFFER_SIZE));
sendRelay.Start(); var sendRelay = new Task(() => StreamHelper.CopyTo(sb.ToString(), clientStream, tunnelStream, BUFFER_SIZE));
receiveRelay.Start(); var receiveRelay = new Task(() => StreamHelper.CopyTo(tunnelStream, clientStream, BUFFER_SIZE));
Task.WaitAll(sendRelay, receiveRelay); sendRelay.Start();
receiveRelay.Start();
if (tunnelStream != null) Task.WaitAll(sendRelay, receiveRelay);
tunnelStream.Close(); }
catch
{
if (tunnelStream != null)
{
tunnelStream.Close();
tunnelStream.Dispose();
}
if (tunnelClient != null) if (tunnelClient != null)
tunnelClient.Close(); tunnelClient.Close();
throw;
}
} }
} }
} }
\ No newline at end of file
...@@ -13,6 +13,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -13,6 +13,7 @@ namespace Titanium.Web.Proxy.Models
internal int BUFFER_SIZE; internal int BUFFER_SIZE;
internal TcpClient Client { get; set; }
internal Stream ClientStream { get; set; } internal Stream ClientStream { get; set; }
internal CustomBinaryReader ClientStreamReader { get; set; } internal CustomBinaryReader ClientStreamReader { get; set; }
internal StreamWriter ClientStreamWriter { get; set; } internal StreamWriter ClientStreamWriter { get; set; }
...@@ -30,8 +31,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -30,8 +31,7 @@ namespace Titanium.Web.Proxy.Models
internal string ResponseHtmlBody { get; set; } internal string ResponseHtmlBody { get; set; }
internal bool ResponseWasModified { get; set; } internal bool ResponseWasModified { get; set; }
public TcpClient Client { get; set; }
public int ClientPort { get; set; } public int ClientPort { get; set; }
public IPAddress ClientIpAddress { get; set; } public IPAddress ClientIpAddress { get; set; }
public string tunnelHostName { get; set; } public string tunnelHostName { get; set; }
...@@ -54,17 +54,6 @@ namespace Titanium.Web.Proxy.Models ...@@ -54,17 +54,6 @@ namespace Titanium.Web.Proxy.Models
if (this.ServerResponse != null) if (this.ServerResponse != null)
this.ServerResponse.Close(); this.ServerResponse.Close();
if (this.ClientStreamReader != null)
this.ClientStreamReader.Dispose();
if (this.ClientStreamWriter != null)
this.ClientStreamWriter.Dispose();
if (this.ClientStream != null)
this.ClientStream.Dispose();
if (this.Client != null)
this.Client.Close();
} }
public SessionEventArgs(int bufferSize) public SessionEventArgs(int bufferSize)
......
...@@ -33,8 +33,6 @@ namespace Titanium.Web.Proxy ...@@ -33,8 +33,6 @@ namespace Titanium.Web.Proxy
private static object certificateAccessLock = new object(); private static object certificateAccessLock = new object();
private static List<string> pinnedCertificateClients = new List<string>(); private static List<string> pinnedCertificateClients = new List<string>();
private static TcpListener listener; private static TcpListener listener;
private static Thread listenerThread; private static Thread listenerThread;
...@@ -43,8 +41,6 @@ namespace Titanium.Web.Proxy ...@@ -43,8 +41,6 @@ namespace Titanium.Web.Proxy
public static event EventHandler<SessionEventArgs> BeforeRequest; public static event EventHandler<SessionEventArgs> BeforeRequest;
public static event EventHandler<SessionEventArgs> BeforeResponse; public static event EventHandler<SessionEventArgs> BeforeResponse;
public static IPAddress ListeningIPInterface { get; set; } public static IPAddress ListeningIPInterface { get; set; }
public static string RootCertificateName { get; set; } public static string RootCertificateName { get; set; }
...@@ -94,25 +90,27 @@ namespace Titanium.Web.Proxy ...@@ -94,25 +90,27 @@ namespace Titanium.Web.Proxy
{ {
TcpListener listener = (TcpListener)obj; TcpListener listener = (TcpListener)obj;
try while (ShouldListen)
{ {
while (ShouldListen) TcpClient client = null;
try
{ {
client = listener.AcceptTcpClient();
var client = listener.AcceptTcpClient();
Task.Factory.StartNew(() => HandleClient(client)); Task.Factory.StartNew(() => HandleClient(client));
}
catch
{
if (client != null)
client.Close();
} }
} }
catch (ThreadInterruptedException) { }
catch (SocketException) { }
} }
public static bool Start() public static bool Start()
{ {
listener = new TcpListener(IPAddress.Any, 0); listener = new TcpListener(IPAddress.Any, 0);
listener.Start(); listener.Start();
listenerThread = new Thread(new ParameterizedThreadStart(Listen)); listenerThread = new Thread(new ParameterizedThreadStart(Listen));
...@@ -125,7 +123,7 @@ namespace Titanium.Web.Proxy ...@@ -125,7 +123,7 @@ namespace Titanium.Web.Proxy
SystemProxyHelper.EnableProxyHTTP("localhost", ListeningPort); SystemProxyHelper.EnableProxyHTTP("localhost", ListeningPort);
FireFoxHelper.AddFirefox(); FireFoxHelper.AddFirefox();
if (EnableSSL) if (EnableSSL)
{ {
RootCertificateName = RootCertificateName == null ? "Titanium_Proxy_Test_Root" : RootCertificateName; RootCertificateName = RootCertificateName == null ? "Titanium_Proxy_Test_Root" : RootCertificateName;
...@@ -137,7 +135,7 @@ namespace Titanium.Web.Proxy ...@@ -137,7 +135,7 @@ namespace Titanium.Web.Proxy
SystemProxyHelper.EnableProxyHTTPS("localhost", ListeningPort); SystemProxyHelper.EnableProxyHTTPS("localhost", ListeningPort);
} }
} }
} }
...@@ -156,12 +154,13 @@ namespace Titanium.Web.Proxy ...@@ -156,12 +154,13 @@ namespace Titanium.Web.Proxy
ShouldListen = false; ShouldListen = false;
listener.Stop(); listener.Stop();
listenerThread.Interrupt(); listenerThread.Interrupt();
CertManager.Dispose();
} }
......
...@@ -25,20 +25,18 @@ namespace Titanium.Web.Proxy ...@@ -25,20 +25,18 @@ namespace Titanium.Web.Proxy
private static void HandleClient(TcpClient client) private static void HandleClient(TcpClient client)
{ {
Stream clientStream = null; Stream clientStream = client.GetStream();
CustomBinaryReader clientStreamReader = null; CustomBinaryReader clientStreamReader = new CustomBinaryReader(clientStream, Encoding.ASCII);
StreamWriter connectStreamWriter = null; StreamWriter clientStreamWriter = new StreamWriter(clientStream);
string tunnelHostName = null; string tunnelHostName = null;
int tunnelPort = 0; int tunnelPort = 0;
try try
{ {
clientStream = client.GetStream();
clientStreamReader = new CustomBinaryReader(clientStream, Encoding.ASCII);
string securehost = null; string securehost = null;
List<string> requestLines = new List<string>(); List<string> requestLines = new List<string>();
...@@ -101,12 +99,11 @@ namespace Titanium.Web.Proxy ...@@ -101,12 +99,11 @@ namespace Titanium.Web.Proxy
} }
requestLines.Clear(); requestLines.Clear();
connectStreamWriter = new StreamWriter(clientStream); clientStreamWriter.WriteLine(RequestVersion + " 200 Connection established");
connectStreamWriter.WriteLine(RequestVersion + " 200 Connection established"); clientStreamWriter.WriteLine(String.Format("Timestamp: {0}", DateTime.Now.ToString()));
connectStreamWriter.WriteLine(String.Format("Timestamp: {0}", DateTime.Now.ToString())); clientStreamWriter.WriteLine(String.Format("connection:close"));
connectStreamWriter.WriteLine(String.Format("connection:close")); clientStreamWriter.WriteLine();
connectStreamWriter.WriteLine(); clientStreamWriter.Flush();
connectStreamWriter.Flush();
//If port is not 443 its not a HTTP request, so just relay //If port is not 443 its not a HTTP request, so just relay
...@@ -114,15 +111,24 @@ namespace Titanium.Web.Proxy ...@@ -114,15 +111,24 @@ namespace Titanium.Web.Proxy
{ {
TcpHelper.SendRaw(tunnelHostName, tunnelPort, clientStreamReader.BaseStream); TcpHelper.SendRaw(tunnelHostName, tunnelPort, clientStreamReader.BaseStream);
if (clientStreamReader != null)
clientStreamReader.Dispose();
if (clientStreamWriter != null)
clientStreamWriter.Dispose();
if (clientStream != null) if (clientStream != null)
clientStream.Close(); clientStream.Dispose();
if (client != null)
client.Close();
return; return;
} }
//Create the fake certificate signed using our fake certificate authority //Create the fake certificate signed using our fake certificate authority
Monitor.Enter(certificateAccessLock); Monitor.Enter(certificateAccessLock);
var _certificate = ProxyServer.CertManager.CreateCertificate(tunnelHostName); var certificate = ProxyServer.CertManager.CreateCertificate(tunnelHostName);
Monitor.Exit(certificateAccessLock); Monitor.Exit(certificateAccessLock);
SslStream sslStream = null; SslStream sslStream = null;
...@@ -131,14 +137,20 @@ namespace Titanium.Web.Proxy ...@@ -131,14 +137,20 @@ namespace Titanium.Web.Proxy
//So just relay the request after identifying it by first failure //So just relay the request after identifying it by first failure
if (!pinnedCertificateClients.Contains(tunnelHostName) && isSecure) if (!pinnedCertificateClients.Contains(tunnelHostName) && isSecure)
{ {
sslStream = new SslStream(clientStream, true);
try try
{ {
sslStream = new SslStream(clientStream, true);
//Successfully managed to authenticate the client using the fake certificate //Successfully managed to authenticate the client using the fake certificate
sslStream.AuthenticateAsServer(_certificate, false, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, false); sslStream.AuthenticateAsServer(certificate, false, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, false);
clientStreamReader = new CustomBinaryReader(sslStream, Encoding.ASCII);
clientStreamWriter = new StreamWriter(sslStream);
//HTTPS server created - we can now decrypt the client's traffic
clientStream = sslStream;
} }
catch (AuthenticationException) catch
{ {
//if authentication failed it could be because client uses pinned certificates //if authentication failed it could be because client uses pinned certificates
//So add the hostname to this list so that next time we can relay without touching it (tunnel the request) //So add the hostname to this list so that next time we can relay without touching it (tunnel the request)
...@@ -146,6 +158,10 @@ namespace Titanium.Web.Proxy ...@@ -146,6 +158,10 @@ namespace Titanium.Web.Proxy
{ {
pinnedCertificateClients.Add(tunnelHostName); pinnedCertificateClients.Add(tunnelHostName);
} }
if (sslStream != null)
sslStream.Dispose();
throw; throw;
} }
...@@ -155,14 +171,21 @@ namespace Titanium.Web.Proxy ...@@ -155,14 +171,21 @@ namespace Titanium.Web.Proxy
//Hostname was a previously failed request due to certificate pinning, just relay (tunnel the request) //Hostname was a previously failed request due to certificate pinning, just relay (tunnel the request)
TcpHelper.SendRaw(tunnelHostName, tunnelPort, clientStreamReader.BaseStream); TcpHelper.SendRaw(tunnelHostName, tunnelPort, clientStreamReader.BaseStream);
if (clientStreamReader != null)
clientStreamReader.Dispose();
if (clientStreamWriter != null)
clientStreamWriter.Dispose();
if (clientStream != null) if (clientStream != null)
clientStream.Close(); clientStream.Dispose();
if (client != null)
client.Close();
return; return;
} }
clientStreamReader = new CustomBinaryReader(sslStream, Encoding.ASCII);
//HTTPS server created - we can now decrypt the client's traffic
clientStream = sslStream;
while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine())) while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine()))
{ {
...@@ -180,48 +203,55 @@ namespace Titanium.Web.Proxy ...@@ -180,48 +203,55 @@ namespace Titanium.Web.Proxy
} }
//Now create the request //Now create the request
Task.Factory.StartNew(()=>HandleHttpSessionRequest(client, httpCmd, clientStream, tunnelHostName, requestLines, clientStreamReader, securehost)); Task.Factory.StartNew(() => HandleHttpSessionRequest(client, httpCmd, clientStream, tunnelHostName, requestLines, clientStreamReader, clientStreamWriter, securehost));
} }
catch (AuthenticationException) catch
{
return;
}
catch (EndOfStreamException)
{
return;
}
catch (IOException)
{
return;
}
catch (UriFormatException)
{
return;
}
catch (WebException)
{
return;
}
finally
{ {
if (clientStreamReader != null)
clientStreamReader.Dispose();
if (clientStreamWriter != null)
clientStreamWriter.Dispose();
if (clientStream != null)
clientStream.Dispose();
if (client != null)
client.Close();
} }
} }
private static void HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream, string tunnelHostName, List<string> requestLines, CustomBinaryReader clientStreamReader, string securehost) private static void HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream, string tunnelHostName, List<string> requestLines, CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, string securehost)
{ {
if (httpCmd == null) return; if (httpCmd == null)
{
if (clientStreamReader != null)
clientStreamReader.Dispose();
if (clientStreamWriter != null)
clientStreamWriter.Dispose();
if (clientStream != null)
clientStream.Dispose();
if (client != null)
client.Close();
return;
}
var args = new SessionEventArgs(BUFFER_SIZE); var args = new SessionEventArgs(BUFFER_SIZE);
args.Client = client; args.Client = client;
args.tunnelHostName = tunnelHostName; args.tunnelHostName = tunnelHostName;
args.securehost = securehost; args.securehost = securehost;
try try
{ {
//break up the line into three components (method, remote URL & Http Version) //break up the line into three components (method, remote URL & Http Version)
...@@ -231,8 +261,20 @@ namespace Titanium.Web.Proxy ...@@ -231,8 +261,20 @@ namespace Titanium.Web.Proxy
{ {
TcpHelper.SendRaw(httpCmd, tunnelHostName, requestLines, args.IsSSLRequest, clientStreamReader.BaseStream); TcpHelper.SendRaw(httpCmd, tunnelHostName, requestLines, args.IsSSLRequest, clientStreamReader.BaseStream);
if (args != null)
args.Dispose();
if (clientStreamReader != null)
clientStreamReader.Dispose();
if (clientStreamWriter != null)
clientStreamWriter.Dispose();
if (clientStream != null) if (clientStream != null)
clientStream.Close(); clientStream.Dispose();
if (client != null)
client.Close();
return; return;
} }
...@@ -262,6 +304,7 @@ namespace Titanium.Web.Proxy ...@@ -262,6 +304,7 @@ namespace Titanium.Web.Proxy
args.ProxyRequest.ProtocolVersion = version; args.ProxyRequest.ProtocolVersion = version;
args.ClientStream = clientStream; args.ClientStream = clientStream;
args.ClientStreamReader = clientStreamReader; args.ClientStreamReader = clientStreamReader;
args.ClientStreamWriter = clientStreamWriter;
for (int i = 1; i < requestLines.Count; i++) for (int i = 1; i < requestLines.Count; i++)
{ {
...@@ -274,8 +317,20 @@ namespace Titanium.Web.Proxy ...@@ -274,8 +317,20 @@ namespace Titanium.Web.Proxy
TcpHelper.SendRaw(httpCmd, tunnelHostName, requestLines, args.IsSSLRequest, clientStreamReader.BaseStream); TcpHelper.SendRaw(httpCmd, tunnelHostName, requestLines, args.IsSSLRequest, clientStreamReader.BaseStream);
if (args != null)
args.Dispose();
if (clientStreamReader != null)
clientStreamReader.Dispose();
if (clientStreamWriter != null)
clientStreamWriter.Dispose();
if (clientStream != null) if (clientStream != null)
clientStream.Close(); clientStream.Dispose();
if (client != null)
client.Close();
return; return;
} }
...@@ -308,19 +363,22 @@ namespace Titanium.Web.Proxy ...@@ -308,19 +363,22 @@ namespace Titanium.Web.Proxy
string tmpLine; string tmpLine;
if (args.CancelRequest) if (args.CancelRequest)
{ {
if (args.RequestIsAlive) if (args != null)
{ args.Dispose();
requestLines.Clear();
while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine()))
{
requestLines.Add(tmpLine);
}
httpCmd = requestLines.Count > 0 ? requestLines[0] : null; if (clientStreamReader != null)
return; clientStreamReader.Dispose();
}
else if (clientStreamWriter != null)
return; clientStreamWriter.Dispose();
if (clientStream != null)
clientStream.Dispose();
if (client != null)
client.Close();
return;
} }
args.ProxyRequest.ConnectionGroupName = args.RequestHostname; args.ProxyRequest.ConnectionGroupName = args.RequestHostname;
...@@ -347,7 +405,7 @@ namespace Titanium.Web.Proxy ...@@ -347,7 +405,7 @@ namespace Titanium.Web.Proxy
//Http request body sent, now wait asynchronously for response //Http request body sent, now wait asynchronously for response
args.ProxyRequest.BeginGetResponse(new AsyncCallback(HandleHttpSessionResponse), args); args.ProxyRequest.BeginGetResponse(new AsyncCallback(HandleHttpSessionResponse), args);
} }
else else
{ {
...@@ -359,37 +417,39 @@ namespace Titanium.Web.Proxy ...@@ -359,37 +417,39 @@ namespace Titanium.Web.Proxy
//Now read the next request (if keep-Alive is enabled, otherwise exit this thread) //Now read the next request (if keep-Alive is enabled, otherwise exit this thread)
//If client is pipeling the request, this will be immediately hit before response for previous request was made //If client is pipeling the request, this will be immediately hit before response for previous request was made
if (args.ProxyRequest.KeepAlive)
{
tmpLine = null;
requestLines.Clear();
while (!String.IsNullOrEmpty(tmpLine = args.ClientStreamReader.ReadLine()))
{
requestLines.Add(tmpLine);
}
httpCmd = requestLines.Count() > 0 ? requestLines[0] : null;
TcpClient Client = args.Client;
//Http request body sent, now wait for next request tmpLine = null;
Task.Factory.StartNew(() => HandleHttpSessionRequest(Client, httpCmd, args.ClientStream, args.tunnelHostName, requestLines, args.ClientStreamReader, args.securehost)); requestLines.Clear();
while (!String.IsNullOrEmpty(tmpLine = args.ClientStreamReader.ReadLine()))
{
requestLines.Add(tmpLine);
} }
httpCmd = requestLines.Count() > 0 ? requestLines[0] : null;
TcpClient Client = args.Client;
//Http request body sent, now wait for next request
Task.Factory.StartNew(() => HandleHttpSessionRequest(Client, httpCmd, args.ClientStream, args.tunnelHostName, requestLines, args.ClientStreamReader, args.ClientStreamWriter, args.securehost));
} }
catch (IOException) catch
{
return;
}
catch (UriFormatException)
{
return;
}
catch (WebException)
{
return;
}
finally
{ {
if (args != null)
args.Dispose();
if (clientStreamReader != null)
clientStreamReader.Dispose();
if (clientStreamWriter != null)
clientStreamWriter.Dispose();
if (clientStream != null)
clientStream.Dispose();
if (client != null)
client.Close();
} }
} }
...@@ -488,7 +548,7 @@ namespace Titanium.Web.Proxy ...@@ -488,7 +548,7 @@ namespace Titanium.Web.Proxy
//This is called when the request is PUT/POST to read the body //This is called when the request is PUT/POST to read the body
private static void SendClientRequestBody(SessionEventArgs args) private static void SendClientRequestBody(SessionEventArgs args)
{ {
// End the operation // End the operation
Stream postStream = args.ProxyRequest.GetRequestStream(); Stream postStream = args.ProxyRequest.GetRequestStream();
...@@ -527,22 +587,16 @@ namespace Titanium.Web.Proxy ...@@ -527,22 +587,16 @@ namespace Titanium.Web.Proxy
postStream.Close(); postStream.Close();
} }
catch (IOException) catch
{
args.ProxyRequest.KeepAlive = false;
throw;
}
catch (WebException)
{ {
if (postStream != null)
postStream.Close();
args.ProxyRequest.KeepAlive = false;
throw; throw;
} }
} }
//Need to revist, find any potential bugs //Need to revist, find any potential bugs
else if (args.ProxyRequest.SendChunked) else if (args.ProxyRequest.SendChunked)
{ {
args.ProxyRequest.AllowWriteStreamBuffering = true; args.ProxyRequest.AllowWriteStreamBuffering = true;
...@@ -598,32 +652,24 @@ namespace Titanium.Web.Proxy ...@@ -598,32 +652,24 @@ namespace Titanium.Web.Proxy
args.ClientStream.ReadByte(); args.ClientStream.ReadByte();
} }
sb.Clear(); sb.Clear();
} }
} }
postStream.Close(); postStream.Close();
} }
catch (IOException) catch
{ {
if (postStream != null) if (postStream != null)
postStream.Close(); postStream.Close();
args.ProxyRequest.KeepAlive = false;
throw; throw;
} }
catch (WebException)
{ }
if (postStream != null)
postStream.Close();
args.ProxyRequest.KeepAlive = false;
throw;
}
}
} }
......
...@@ -22,6 +22,7 @@ namespace Titanium.Web.Proxy ...@@ -22,6 +22,7 @@ namespace Titanium.Web.Proxy
{ {
SessionEventArgs args = (SessionEventArgs)asynchronousResult.AsyncState; SessionEventArgs args = (SessionEventArgs)asynchronousResult.AsyncState;
try try
{ {
args.ServerResponse = (HttpWebResponse)args.ProxyRequest.EndGetResponse(asynchronousResult); args.ServerResponse = (HttpWebResponse)args.ProxyRequest.EndGetResponse(asynchronousResult);
...@@ -29,27 +30,18 @@ namespace Titanium.Web.Proxy ...@@ -29,27 +30,18 @@ namespace Titanium.Web.Proxy
catch (WebException webEx) catch (WebException webEx)
{ {
//Things line 404, 500 etc //Things line 404, 500 etc
//args.ProxyRequest.KeepAlive = false;
args.ServerResponse = webEx.Response as HttpWebResponse; args.ServerResponse = webEx.Response as HttpWebResponse;
} }
try try
{ {
if (args.ClientStreamWriter == null)
{
args.ClientStreamWriter = new StreamWriter(args.ClientStream);
}
if (args.ServerResponse != null) if (args.ServerResponse != null)
{ {
List<Tuple<String, String>> responseHeaders = ProcessResponse(args.ServerResponse); List<Tuple<String, String>> responseHeaders = ProcessResponse(args.ServerResponse);
args.ServerResponseStream = args.ServerResponse.GetResponseStream(); args.ServerResponseStream = args.ServerResponse.GetResponseStream();
if (args.ServerResponse.Headers.Count == 0 && args.ServerResponse.ContentLength == -1)
args.ProxyRequest.KeepAlive = false;
bool isChunked = args.ServerResponse.GetResponseHeader("transfer-encoding") == null ? false : args.ServerResponse.GetResponseHeader("transfer-encoding").ToLower() == "chunked" ? true : false; bool isChunked = args.ServerResponse.GetResponseHeader("transfer-encoding") == null ? false : args.ServerResponse.GetResponseHeader("transfer-encoding").ToLower() == "chunked" ? true : false;
args.ProxyRequest.KeepAlive = args.ServerResponse.GetResponseHeader("connection") == null ? args.ProxyRequest.KeepAlive : (args.ServerResponse.GetResponseHeader("connection") == "close" ? false : args.ProxyRequest.KeepAlive);
args.UpgradeProtocol = args.ServerResponse.GetResponseHeader("upgrade") == null ? null : args.ServerResponse.GetResponseHeader("upgrade"); args.UpgradeProtocol = args.ServerResponse.GetResponseHeader("upgrade") == null ? null : args.ServerResponse.GetResponseHeader("upgrade");
if (BeforeResponse != null) if (BeforeResponse != null)
...@@ -103,49 +95,30 @@ namespace Titanium.Web.Proxy ...@@ -103,49 +95,30 @@ namespace Titanium.Web.Proxy
args.ClientStream.Flush(); args.ClientStream.Flush();
} }
else
args.ProxyRequest.KeepAlive = false;
} }
catch (IOException) catch
{
args.ProxyRequest.KeepAlive = false;
}
catch (SocketException)
{
args.ProxyRequest.KeepAlive = false;
}
catch (ArgumentException)
{
args.ProxyRequest.KeepAlive = false;
}
catch (WebException)
{ {
args.ProxyRequest.KeepAlive = false; if (args.ClientStreamReader != null)
} args.ClientStreamReader.Dispose();
finally
{
//If this is false then terminate the tcp client
if (args.ProxyRequest.KeepAlive == false)
{
args.Dispose();
}
else
{
//Close this HttpWebRequest session if (args.ClientStreamWriter != null)
if (args.ProxyRequest != null) args.ClientStreamWriter.Dispose();
args.ProxyRequest.Abort();
if (args.ServerResponse != null) if (args.ClientStream != null)
args.ServerResponse.Close(); args.ClientStream.Dispose();
if (args.ServerResponseStream != null) if (args.Client != null)
args.ServerResponseStream.Close(); args.Client.Close();
} }
finally
{
if (args != null)
args.Dispose();
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment