diff --git a/Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs b/Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs index aca960bb1..7217a2719 100644 --- a/Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs +++ b/Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs @@ -22,7 +22,7 @@ internal class CustomBinaryReader : IDisposable private static readonly ConcurrentQueue buffers = new ConcurrentQueue(); - private volatile bool disposed = false; + private volatile bool disposed; internal CustomBinaryReader(CustomBufferedStream stream, int bufferSize) { diff --git a/Titanium.Web.Proxy/ProxyServer.cs b/Titanium.Web.Proxy/ProxyServer.cs index 8eccc0da7..a912b0d53 100644 --- a/Titanium.Web.Proxy/ProxyServer.cs +++ b/Titanium.Web.Proxy/ProxyServer.cs @@ -383,8 +383,7 @@ public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint) #if !DEBUG firefoxProxySettingsManager.AddFirefox(); #endif - Console.WriteLine("Set endpoint at Ip {0} and port: {1} as System HTTPS Proxy", - endPoint.IpAddress, endPoint.Port); + Console.WriteLine("Set endpoint at Ip {0} and port: {1} as System HTTPS Proxy", endPoint.IpAddress, endPoint.Port); } /// diff --git a/Titanium.Web.Proxy/RequestHandler.cs b/Titanium.Web.Proxy/RequestHandler.cs index fe76c51dc..5a0cfda33 100644 --- a/Titanium.Web.Proxy/RequestHandler.cs +++ b/Titanium.Web.Proxy/RequestHandler.cs @@ -117,6 +117,7 @@ private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpCli //Successfully managed to authenticate the client using the fake certificate await sslStream.AuthenticateAsServerAsync(certificate, false, SupportedSslProtocols, false); + //HTTPS server created - we can now decrypt the client's traffic clientStream = new CustomBufferedStream(sslStream, BufferSize); @@ -138,6 +139,7 @@ await sslStream.AuthenticateAsServerAsync(certificate, false, { //Siphon out CONNECT request headers await clientStreamReader.ReadAndIgnoreAllLinesAsync(); + //write back successfull CONNECT response await WriteConnectResponse(clientStreamWriter, version); @@ -172,8 +174,7 @@ await TcpHelper.SendRaw(this, //So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcpClient) { - var disposed = false; - + bool disposed = false; var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize); clientStream.ReadTimeout = ConnectionTimeOutSeconds * 1000; @@ -182,52 +183,39 @@ private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcp CustomBinaryReader clientStreamReader = null; StreamWriter clientStreamWriter = null; - if (endPoint.EnableSsl) + try { - var sslStream = new SslStream(clientStream, true); + if (endPoint.EnableSsl) + { + var sslStream = new SslStream(clientStream, true); + clientStream = new CustomBufferedStream(sslStream, BufferSize); - //implement in future once SNI supported by SSL stream, for now use the same certificate - var certificate = CertificateManager.CreateCertificate(endPoint.GenericCertificateName, false); + //implement in future once SNI supported by SSL stream, for now use the same certificate + var certificate = CertificateManager.CreateCertificate(endPoint.GenericCertificateName, false); - try - { //Successfully managed to authenticate the client using the fake certificate await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false); - clientStream = new CustomBufferedStream(sslStream, BufferSize); - clientStreamReader = new CustomBinaryReader(clientStream, BufferSize); - clientStreamWriter = new StreamWriter(clientStream) { NewLine = ProxyConstants.NewLine }; //HTTPS server created - we can now decrypt the client's traffic } - catch (Exception) - { - sslStream.Dispose(); - - Dispose(sslStream, - clientStreamReader, - clientStreamWriter, null); - disposed = true; - return; - } - } - else - { clientStreamReader = new CustomBinaryReader(clientStream, BufferSize); clientStreamWriter = new StreamWriter(clientStream) { NewLine = ProxyConstants.NewLine }; - } - - //now read the request line - var httpCmd = await clientStreamReader.ReadLineAsync(); - //Now create the request - disposed = await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter, - endPoint.EnableSsl ? endPoint.GenericCertificateName : null, endPoint, null); + //now read the request line + var httpCmd = await clientStreamReader.ReadLineAsync(); - if (!disposed) + //Now create the request + disposed = await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter, + endPoint.EnableSsl ? endPoint.GenericCertificateName : null, endPoint, null); + } + finally { - Dispose(clientStream, clientStreamReader, clientStreamWriter, null); + if (!disposed) + { + Dispose(clientStream, clientStreamReader, clientStreamWriter, null); + } } } @@ -271,9 +259,11 @@ private async Task GetServerConnection( } - private async Task HandleHttpSessionRequestInternal(TcpConnection connection, - SessionEventArgs args, bool closeConnection) + private async Task HandleHttpSessionRequestInternal(TcpConnection connection, SessionEventArgs args, bool closeConnection) { + bool disposed = false; + bool keepAlive = false; + try { args.WebSession.Request.RequestLocked = true; @@ -281,11 +271,6 @@ private async Task HandleHttpSessionRequestInternal(TcpConnection connecti //If request was cancelled by user then dispose the client if (args.WebSession.Request.CancelRequest) { - Dispose(args.ProxyClient.ClientStream, - args.ProxyClient.ClientStreamReader, - args.ProxyClient.ClientStreamWriter, - args.WebSession.ServerConnection); - return true; } @@ -350,50 +335,42 @@ await WriteResponseStatus(args.WebSession.Response.HttpVersion, "417", //If not expectation failed response was returned by server then parse response if (!args.WebSession.Request.ExpectationFailed) { - var disposed = await HandleHttpSessionResponse(args); + disposed = await HandleHttpSessionResponse(args); //already disposed inside above method if (disposed) { - return disposed; + return true; } } //if connection is closing exit if (args.WebSession.Response.ResponseKeepAlive == false) { - Dispose(args.ProxyClient.ClientStream, - args.ProxyClient.ClientStreamReader, - args.ProxyClient.ClientStreamWriter, - args.WebSession.ServerConnection); - return true; } + + if (!closeConnection) + { + keepAlive = true; + return false; + } } catch (Exception e) { ExceptionFunc(new ProxyHttpException("Error occured whilst handling session request (internal)", e, args)); - - Dispose(args.ProxyClient.ClientStream, - args.ProxyClient.ClientStreamReader, - args.ProxyClient.ClientStreamWriter, - args.WebSession.ServerConnection); - return true; } - - if (closeConnection) + finally { - //dispose - Dispose(args.ProxyClient.ClientStream, - args.ProxyClient.ClientStreamReader, - args.ProxyClient.ClientStreamWriter, - args.WebSession.ServerConnection); - - return true; + if (!disposed && !keepAlive) + { + //dispose + Dispose(args.ProxyClient.ClientStream, args.ProxyClient.ClientStreamReader, args.ProxyClient.ClientStreamWriter, args.WebSession.ServerConnection); + } } - return false; + return true; } /// @@ -412,7 +389,7 @@ private async Task HandleHttpSessionRequest(TcpClient client, string httpC CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, string httpsHostName, ProxyEndPoint endPoint, List connectHeaders) { - var disposed = false; + bool disposed = false; TcpConnection connection = null; @@ -422,12 +399,6 @@ private async Task HandleHttpSessionRequest(TcpClient client, string httpC { if (string.IsNullOrEmpty(httpCmd)) { - Dispose(clientStream, - clientStreamReader, - clientStreamWriter, - connection); - - disposed = true; break; } @@ -489,12 +460,6 @@ private async Task HandleHttpSessionRequest(TcpClient client, string httpC await CheckAuthorization(clientStreamWriter, args.WebSession.Request.RequestHeaders.Values) == false) { - Dispose(clientStream, - clientStreamReader, - clientStreamWriter, - connection); - - disposed = true; break; } @@ -515,12 +480,6 @@ await TcpHelper.SendRaw(this, httpCmd, httpVersion, args.WebSession.Request.RequestHeaders, args.IsHttps, clientStream, tcpConnectionFactory); - Dispose(clientStream, - clientStreamReader, - clientStreamWriter, - connection); - - disposed = true; break; } @@ -540,24 +499,12 @@ await TcpHelper.SendRaw(this, if (args.WebSession.Request.CancelRequest) { - Dispose(clientStream, - clientStreamReader, - clientStreamWriter, - connection); - - disposed = true; break; } //if connection is closing exit if (args.WebSession.Response.ResponseKeepAlive == false) { - Dispose(clientStream, - clientStreamReader, - clientStreamWriter, - connection); - - disposed = true; break; } @@ -567,18 +514,16 @@ await TcpHelper.SendRaw(this, catch (Exception e) { ExceptionFunc(new ProxyHttpException("Error occured whilst handling session request", e, args)); - - Dispose(clientStream, - clientStreamReader, - clientStreamWriter, - connection); - - disposed = true; break; } } - return disposed; + if (!disposed) + { + Dispose(clientStream, clientStreamReader, clientStreamWriter, connection); + } + + return true; } /// diff --git a/Titanium.Web.Proxy/ResponseHandler.cs b/Titanium.Web.Proxy/ResponseHandler.cs index 3f4b32619..d9ade74a0 100644 --- a/Titanium.Web.Proxy/ResponseHandler.cs +++ b/Titanium.Web.Proxy/ResponseHandler.cs @@ -53,8 +53,8 @@ private async Task HandleHttpSessionResponse(SessionEventArgs args) } var connection = await GetServerConnection(args); - var result = await HandleHttpSessionRequestInternal(null, args, true); - return result; + var disposed = await HandleHttpSessionRequestInternal(null, args, true); + return disposed; } args.WebSession.Response.ResponseLocked = true;