Commit 8b46f917 authored by justcoding121's avatar justcoding121 Committed by GitHub

Merge pull request #99 from justcoding121/release

Performance: Fix abrupt termination of SSL requests
parents 4456a224 e1cf60d6
...@@ -9,26 +9,37 @@ using System.Text; ...@@ -9,26 +9,37 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Network;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
internal class TcpHelper internal class TcpHelper
{ {
/// <summary> /// <summary>
/// relays the input clientStream to the server at the specified host name & port with the given httpCmd & headers as prefix /// relays the input clientStream to the server at the specified host name & port with the given httpCmd & headers as prefix
/// Usefull for websocket requests /// Usefull for websocket requests
/// </summary> /// </summary>
/// <param name="clientStream"></param> /// <param name="bufferSize"></param>
/// <param name="connectionTimeOutSeconds"></param>
/// <param name="remoteHostName"></param>
/// <param name="httpCmd"></param> /// <param name="httpCmd"></param>
/// <param name="httpVersion"></param>
/// <param name="requestHeaders"></param> /// <param name="requestHeaders"></param>
/// <param name="hostName"></param>
/// <param name="tunnelPort"></param>
/// <param name="isHttps"></param> /// <param name="isHttps"></param>
/// <param name="remotePort"></param>
/// <param name="supportedProtocols"></param>
/// <param name="remoteCertificateValidationCallback"></param>
/// <param name="localCertificateSelectionCallback"></param>
/// <param name="clientStream"></param>
/// <param name="tcpConnectionFactory"></param>
/// <returns></returns> /// <returns></returns>
internal static async Task SendRaw(Stream clientStream, string httpCmd, Dictionary<string, HttpHeader> requestHeaders, string hostName, internal static async Task SendRaw(int bufferSize, int connectionTimeOutSeconds,
int tunnelPort, bool isHttps, SslProtocols supportedProtocols, int connectionTimeOutSeconds) string remoteHostName, int remotePort, string httpCmd, Version httpVersion, Dictionary<string, HttpHeader> requestHeaders,
bool isHttps, SslProtocols supportedProtocols,
RemoteCertificateValidationCallback remoteCertificateValidationCallback, LocalCertificateSelectionCallback localCertificateSelectionCallback,
Stream clientStream, TcpConnectionFactory tcpConnectionFactory)
{ {
//prepare the prefix content //prepare the prefix content
StringBuilder sb = null; StringBuilder sb = null;
...@@ -54,40 +65,17 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -54,40 +65,17 @@ namespace Titanium.Web.Proxy.Helpers
sb.Append(Environment.NewLine); sb.Append(Environment.NewLine);
} }
var tcpConnection = await tcpConnectionFactory.CreateClient(bufferSize, connectionTimeOutSeconds,
TcpClient tunnelClient = null; remoteHostName, remotePort,
Stream tunnelStream = null; httpVersion, isHttps,
//create the TcpClient to the server supportedProtocols, remoteCertificateValidationCallback, localCertificateSelectionCallback,
null, null, clientStream);
try try
{ {
tunnelClient = new TcpClient(hostName, tunnelPort); TcpClient tunnelClient = tcpConnection.TcpClient;
tunnelStream = tunnelClient.GetStream();
if (isHttps)
{
SslStream sslStream = null;
try
{
sslStream = new SslStream(tunnelStream);
await sslStream.AuthenticateAsClientAsync(hostName, null, supportedProtocols, false);
tunnelStream = sslStream;
}
catch
{
if (sslStream != null)
{
sslStream.Dispose();
}
throw;
}
}
tunnelClient.SendTimeout = connectionTimeOutSeconds * 1000;
tunnelClient.ReceiveTimeout = connectionTimeOutSeconds * 1000;
tunnelStream.ReadTimeout = connectionTimeOutSeconds * 1000; Stream tunnelStream = tcpConnection.Stream;
tunnelStream.WriteTimeout = connectionTimeOutSeconds * 1000;
Task sendRelay; Task sendRelay;
...@@ -108,19 +96,13 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -108,19 +96,13 @@ namespace Titanium.Web.Proxy.Helpers
} }
catch catch
{ {
if (tunnelStream != null)
{
tunnelStream.Close();
tunnelStream.Dispose();
}
if (tunnelClient != null)
{
tunnelClient.Close();
}
throw; throw;
} }
finally
{
tcpConnection.Dispose();
}
} }
} }
} }
\ No newline at end of file
...@@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary> /// <summary>
/// An object that holds TcpConnection to a particular server & port /// An object that holds TcpConnection to a particular server & port
/// </summary> /// </summary>
public class TcpConnection: IDisposable public class TcpConnection : IDisposable
{ {
internal string HostName { get; set; } internal string HostName { get; set; }
internal int port { get; set; } internal int port { get; set; }
...@@ -44,11 +44,15 @@ namespace Titanium.Web.Proxy.Network ...@@ -44,11 +44,15 @@ namespace Titanium.Web.Proxy.Network
public void Dispose() public void Dispose()
{ {
Stream.Close();
Stream.Dispose(); Stream.Dispose();
TcpClient.LingerState = new LingerOption(true, 0);
TcpClient.Client.Shutdown(SocketShutdown.Both);
TcpClient.Client.Close(); TcpClient.Client.Close();
TcpClient.Close();
TcpClient.Client.Dispose(); TcpClient.Client.Dispose();
TcpClient.Close();
} }
} }
} }
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.IO; using System.IO;
using System.Net.Security; using System.Net.Security;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using System.Threading;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using System.Security.Authentication; using System.Security.Authentication;
...@@ -19,38 +15,30 @@ namespace Titanium.Web.Proxy.Network ...@@ -19,38 +15,30 @@ namespace Titanium.Web.Proxy.Network
/// </summary> /// </summary>
internal class TcpConnectionFactory internal class TcpConnectionFactory
{ {
/// <summary>
/// Get a TcpConnection to the specified host, port optionally HTTPS and a particular HTTP version
/// </summary>
/// <param name="hostname"></param>
/// <param name="port"></param>
/// <param name="isHttps"></param>
/// <param name="version"></param>
/// <returns></returns>
internal async Task<TcpConnection> GetClient(string hostname, int port, bool isHttps, Version version,
ExternalProxy upStreamHttpProxy, ExternalProxy upStreamHttpsProxy, int bufferSize, SslProtocols supportedSslProtocols,
int connectionTimeOutSeconds,
RemoteCertificateValidationCallback remoteCertificateValidationCallBack,
LocalCertificateSelectionCallback localCertificateSelectionCallback)
{
//not in cache so create and return
return await CreateClient(hostname, port, isHttps, version, connectionTimeOutSeconds, upStreamHttpProxy, upStreamHttpsProxy, bufferSize, supportedSslProtocols,
remoteCertificateValidationCallBack, localCertificateSelectionCallback);
}
/// <summary> /// <summary>
/// Create connection to a particular host/port optionally with SSL and a particular HTTP version /// Creates a TCP connection to server
/// </summary> /// </summary>
/// <param name="hostname"></param> /// <param name="bufferSize"></param>
/// <param name="port"></param> /// <param name="connectionTimeOutSeconds"></param>
/// <param name="remoteHostName"></param>
/// <param name="httpCmd"></param>
/// <param name="httpVersion"></param>
/// <param name="isHttps"></param> /// <param name="isHttps"></param>
/// <param name="version"></param> /// <param name="remotePort"></param>
/// <param name="supportedSslProtocols"></param>
/// <param name="remoteCertificateValidationCallback"></param>
/// <param name="localCertificateSelectionCallback"></param>
/// <param name="externalHttpProxy"></param>
/// <param name="externalHttpsProxy"></param>
/// <param name="clientStream"></param>
/// <returns></returns> /// <returns></returns>
private async Task<TcpConnection> CreateClient(string hostname, int port, bool isHttps, Version version, int connectionTimeOutSeconds, internal async Task<TcpConnection> CreateClient(int bufferSize, int connectionTimeOutSeconds,
ExternalProxy upStreamHttpProxy, ExternalProxy upStreamHttpsProxy, int bufferSize, SslProtocols supportedSslProtocols, string remoteHostName, int remotePort, Version httpVersion,
RemoteCertificateValidationCallback remoteCertificateValidationCallBack, LocalCertificateSelectionCallback localCertificateSelectionCallback) bool isHttps, SslProtocols supportedSslProtocols,
RemoteCertificateValidationCallback remoteCertificateValidationCallback, LocalCertificateSelectionCallback localCertificateSelectionCallback,
ExternalProxy externalHttpProxy, ExternalProxy externalHttpsProxy,
Stream clientStream)
{ {
TcpClient client; TcpClient client;
Stream stream; Stream stream;
...@@ -60,15 +48,15 @@ namespace Titanium.Web.Proxy.Network ...@@ -60,15 +48,15 @@ namespace Titanium.Web.Proxy.Network
SslStream sslStream = null; SslStream sslStream = null;
//If this proxy uses another external proxy then create a tunnel request for HTTPS connections //If this proxy uses another external proxy then create a tunnel request for HTTPS connections
if (upStreamHttpsProxy != null) if (externalHttpsProxy != null)
{ {
client = new TcpClient(upStreamHttpsProxy.HostName, upStreamHttpsProxy.Port); client = new TcpClient(externalHttpsProxy.HostName, externalHttpsProxy.Port);
stream = client.GetStream(); stream = client.GetStream();
using (var writer = new StreamWriter(stream, Encoding.ASCII, bufferSize, true)) using (var writer = new StreamWriter(stream, Encoding.ASCII, bufferSize, true))
{ {
await writer.WriteLineAsync(string.Format("CONNECT {0}:{1} {2}", hostname, port, version)); await writer.WriteLineAsync(string.Format("CONNECT {0}:{1} {2}", remoteHostName, remotePort, httpVersion));
await writer.WriteLineAsync(string.Format("Host: {0}:{1}", hostname, port)); await writer.WriteLineAsync(string.Format("Host: {0}:{1}", remoteHostName, remotePort));
await writer.WriteLineAsync("Connection: Keep-Alive"); await writer.WriteLineAsync("Connection: Keep-Alive");
await writer.WriteLineAsync(); await writer.WriteLineAsync();
await writer.FlushAsync(); await writer.FlushAsync();
...@@ -89,16 +77,16 @@ namespace Titanium.Web.Proxy.Network ...@@ -89,16 +77,16 @@ namespace Titanium.Web.Proxy.Network
} }
else else
{ {
client = new TcpClient(hostname, port); client = new TcpClient(remoteHostName, remotePort);
stream = client.GetStream(); stream = client.GetStream();
} }
try try
{ {
sslStream = new SslStream(stream, true, remoteCertificateValidationCallBack, sslStream = new SslStream(stream, true, remoteCertificateValidationCallback,
localCertificateSelectionCallback); localCertificateSelectionCallback);
await sslStream.AuthenticateAsClientAsync(hostname, null, supportedSslProtocols, false); await sslStream.AuthenticateAsClientAsync(remoteHostName, null, supportedSslProtocols, false);
stream = sslStream; stream = sslStream;
} }
...@@ -114,14 +102,14 @@ namespace Titanium.Web.Proxy.Network ...@@ -114,14 +102,14 @@ namespace Titanium.Web.Proxy.Network
} }
else else
{ {
if (upStreamHttpProxy != null) if (externalHttpProxy != null)
{ {
client = new TcpClient(upStreamHttpProxy.HostName, upStreamHttpProxy.Port); client = new TcpClient(externalHttpProxy.HostName, externalHttpProxy.Port);
stream = client.GetStream(); stream = client.GetStream();
} }
else else
{ {
client = new TcpClient(hostname, port); client = new TcpClient(remoteHostName, remotePort);
stream = client.GetStream(); stream = client.GetStream();
} }
} }
...@@ -132,15 +120,17 @@ namespace Titanium.Web.Proxy.Network ...@@ -132,15 +120,17 @@ namespace Titanium.Web.Proxy.Network
stream.ReadTimeout = connectionTimeOutSeconds * 1000; stream.ReadTimeout = connectionTimeOutSeconds * 1000;
stream.WriteTimeout = connectionTimeOutSeconds * 1000; stream.WriteTimeout = connectionTimeOutSeconds * 1000;
client.NoDelay = true;
return new TcpConnection() return new TcpConnection()
{ {
HostName = hostname, HostName = remoteHostName,
port = port, port = remotePort,
IsHttps = isHttps, IsHttps = isHttps,
TcpClient = client, TcpClient = client,
StreamReader = new CustomBinaryReader(stream), StreamReader = new CustomBinaryReader(stream),
Stream = stream, Stream = stream,
Version = version Version = httpVersion
}; };
} }
......
...@@ -15,9 +15,9 @@ namespace Titanium.Web.Proxy ...@@ -15,9 +15,9 @@ namespace Titanium.Web.Proxy
/// <summary> /// <summary>
/// Proxy Server Main class /// Proxy Server Main class
/// </summary> /// </summary>
public partial class ProxyServer: IDisposable public partial class ProxyServer : IDisposable
{ {
/// <summary> /// <summary>
/// Manages certificates used by this proxy /// Manages certificates used by this proxy
/// </summary> /// </summary>
...@@ -197,7 +197,7 @@ namespace Titanium.Web.Proxy ...@@ -197,7 +197,7 @@ namespace Titanium.Web.Proxy
Console.WriteLine("Set endpoint at Ip {1} and port: {2} as System HTTP Proxy", endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port); Console.WriteLine("Set endpoint at Ip {1} and port: {2} as System HTTP Proxy", endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
} }
/// <summary> /// <summary>
/// Set the given explicit end point as the default proxy server for current machine /// Set the given explicit end point as the default proxy server for current machine
...@@ -360,17 +360,12 @@ namespace Titanium.Web.Proxy ...@@ -360,17 +360,12 @@ namespace Titanium.Web.Proxy
{ {
var endPoint = (ProxyEndPoint)asyn.AsyncState; var endPoint = (ProxyEndPoint)asyn.AsyncState;
TcpClient tcpClient = null;
try try
{ {
//based on end point type call appropriate request handlers //based on end point type call appropriate request handlers
var client = endPoint.listener.EndAcceptTcpClient(asyn); tcpClient = endPoint.listener.EndAcceptTcpClient(asyn);
if (endPoint.GetType() == typeof(TransparentProxyEndPoint))
HandleClient(endPoint as TransparentProxyEndPoint, client);
else
HandleClient(endPoint as ExplicitProxyEndPoint, client);
// Get the listener that handles the client request.
endPoint.listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint);
} }
catch (ObjectDisposedException) catch (ObjectDisposedException)
{ {
...@@ -384,6 +379,43 @@ namespace Titanium.Web.Proxy ...@@ -384,6 +379,43 @@ namespace Titanium.Web.Proxy
//Other errors are discarded to keep proxy running //Other errors are discarded to keep proxy running
} }
if (tcpClient != null)
{
Task.Run(async () =>
{
try
{
tcpClient.NoDelay = true;
if (endPoint.GetType() == typeof(TransparentProxyEndPoint))
{
await HandleClient(endPoint as TransparentProxyEndPoint, tcpClient);
}
else
{
await HandleClient(endPoint as ExplicitProxyEndPoint, tcpClient);
}
}
finally
{
if (tcpClient != null)
{
tcpClient.LingerState = new LingerOption(true, 0);
tcpClient.Client.Shutdown(SocketShutdown.Both);
tcpClient.Client.Close();
tcpClient.Client.Dispose();
tcpClient.Close();
}
}
});
}
// Get the listener that handles the client request.
endPoint.listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint);
} }
public void Dispose() public void Dispose()
......
...@@ -25,7 +25,7 @@ namespace Titanium.Web.Proxy ...@@ -25,7 +25,7 @@ namespace Titanium.Web.Proxy
{ {
//This is called when client is aware of proxy //This is called when client is aware of proxy
//So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy //So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
private async void HandleClient(ExplicitProxyEndPoint endPoint, TcpClient client) private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient client)
{ {
Stream clientStream = client.GetStream(); Stream clientStream = client.GetStream();
...@@ -43,7 +43,7 @@ namespace Titanium.Web.Proxy ...@@ -43,7 +43,7 @@ namespace Titanium.Web.Proxy
if (string.IsNullOrEmpty(httpCmd)) if (string.IsNullOrEmpty(httpCmd))
{ {
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null); Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
return; return;
} }
...@@ -109,7 +109,7 @@ namespace Titanium.Web.Proxy ...@@ -109,7 +109,7 @@ namespace Titanium.Web.Proxy
sslStream.Dispose(); sslStream.Dispose();
} }
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null); Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
return; return;
} }
...@@ -125,11 +125,15 @@ namespace Titanium.Web.Proxy ...@@ -125,11 +125,15 @@ namespace Titanium.Web.Proxy
//write back successfull CONNECT response //write back successfull CONNECT response
await WriteConnectResponse(clientStreamWriter, version); await WriteConnectResponse(clientStreamWriter, version);
//Just relay the request/response without decrypting it
await TcpHelper.SendRaw(clientStream, null, null, httpRemoteUri.Host, httpRemoteUri.Port,
false, SupportedSslProtocols, ConnectionTimeOutSeconds);
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null); await TcpHelper.SendRaw(BUFFER_SIZE, ConnectionTimeOutSeconds, httpRemoteUri.Host, httpRemoteUri.Port,
httpCmd, version, null,
false, SupportedSslProtocols,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
new LocalCertificateSelectionCallback(SelectClientCertificate),
clientStream, tcpConnectionFactory);
Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
return; return;
} }
...@@ -139,13 +143,13 @@ namespace Titanium.Web.Proxy ...@@ -139,13 +143,13 @@ namespace Titanium.Web.Proxy
} }
catch catch
{ {
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null); Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
} }
} }
//This is called when this proxy acts as a reverse proxy (like a real http server) //This is called when this proxy acts as a reverse proxy (like a real http server)
//So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client //So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client
private async void HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcpClient) private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcpClient)
{ {
Stream clientStream = tcpClient.GetStream(); Stream clientStream = tcpClient.GetStream();
...@@ -181,7 +185,7 @@ namespace Titanium.Web.Proxy ...@@ -181,7 +185,7 @@ namespace Titanium.Web.Proxy
sslStream.Dispose(); sslStream.Dispose();
} }
Dispose(tcpClient, sslStream, clientStreamReader, clientStreamWriter, null); Dispose(sslStream, clientStreamReader, clientStreamWriter, null);
return; return;
} }
clientStream = sslStream; clientStream = sslStream;
...@@ -219,7 +223,7 @@ namespace Titanium.Web.Proxy ...@@ -219,7 +223,7 @@ namespace Titanium.Web.Proxy
{ {
if (string.IsNullOrEmpty(httpCmd)) if (string.IsNullOrEmpty(httpCmd))
{ {
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null); Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
break; break;
} }
...@@ -234,14 +238,14 @@ namespace Titanium.Web.Proxy ...@@ -234,14 +238,14 @@ namespace Titanium.Web.Proxy
var httpMethod = httpCmdSplit[0]; var httpMethod = httpCmdSplit[0];
//find the request HTTP version //find the request HTTP version
Version version = new Version(1, 1); Version httpVersion = new Version(1, 1);
if (httpCmdSplit.Length == 3) if (httpCmdSplit.Length == 3)
{ {
var httpVersion = httpCmdSplit[2].ToLower().Trim(); var httpVersionString = httpCmdSplit[2].ToLower().Trim();
if (httpVersion == "http/1.0") if (httpVersionString == "http/1.0")
{ {
version = new Version(1, 0); httpVersion = new Version(1, 0);
} }
} }
...@@ -285,7 +289,7 @@ namespace Titanium.Web.Proxy ...@@ -285,7 +289,7 @@ namespace Titanium.Web.Proxy
args.WebSession.Request.RequestUri = httpRemoteUri; args.WebSession.Request.RequestUri = httpRemoteUri;
args.WebSession.Request.Method = httpMethod; args.WebSession.Request.Method = httpMethod;
args.WebSession.Request.HttpVersion = version; args.WebSession.Request.HttpVersion = httpVersion;
args.ProxyClient.ClientStream = clientStream; args.ProxyClient.ClientStream = clientStream;
args.ProxyClient.ClientStreamReader = clientStreamReader; args.ProxyClient.ClientStreamReader = clientStreamReader;
args.ProxyClient.ClientStreamWriter = clientStreamWriter; args.ProxyClient.ClientStreamWriter = clientStreamWriter;
...@@ -310,24 +314,33 @@ namespace Titanium.Web.Proxy ...@@ -310,24 +314,33 @@ namespace Titanium.Web.Proxy
//if upgrading to websocket then relay the requet without reading the contents //if upgrading to websocket then relay the requet without reading the contents
if (args.WebSession.Request.UpgradeToWebSocket) if (args.WebSession.Request.UpgradeToWebSocket)
{ {
await TcpHelper.SendRaw(clientStream, httpCmd, args.WebSession.Request.RequestHeaders, await TcpHelper.SendRaw(BUFFER_SIZE, ConnectionTimeOutSeconds, httpRemoteUri.Host, httpRemoteUri.Port,
httpRemoteUri.Host, httpRemoteUri.Port, args.IsHttps, SupportedSslProtocols, ConnectionTimeOutSeconds); httpCmd, httpVersion, args.WebSession.Request.RequestHeaders, args.IsHttps,
SupportedSslProtocols, new RemoteCertificateValidationCallback(ValidateServerCertificate),
new LocalCertificateSelectionCallback(SelectClientCertificate),
clientStream, tcpConnectionFactory);
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args); Dispose(clientStream, clientStreamReader, clientStreamWriter, args);
break; break;
} }
//construct the web request that we are going to issue on behalf of the client. //construct the web request that we are going to issue on behalf of the client.
connection = connection!=null? connection : await tcpConnectionFactory.GetClient(args.WebSession.Request.RequestUri.Host, args.WebSession.Request.RequestUri.Port, args.IsHttps, version, if (connection == null)
UpStreamHttpProxy, UpStreamHttpsProxy, BUFFER_SIZE, SupportedSslProtocols, ConnectionTimeOutSeconds, new RemoteCertificateValidationCallback(ValidateServerCertificate), {
new LocalCertificateSelectionCallback(SelectClientCertificate)); connection = await tcpConnectionFactory.CreateClient(BUFFER_SIZE, ConnectionTimeOutSeconds,
args.WebSession.Request.RequestUri.Host, args.WebSession.Request.RequestUri.Port, httpVersion,
args.IsHttps, SupportedSslProtocols,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
new LocalCertificateSelectionCallback(SelectClientCertificate),
UpStreamHttpProxy, UpStreamHttpsProxy, clientStream);
}
args.WebSession.Request.RequestLocked = true; args.WebSession.Request.RequestLocked = true;
//If request was cancelled by user then dispose the client //If request was cancelled by user then dispose the client
if (args.WebSession.Request.CancelRequest) if (args.WebSession.Request.CancelRequest)
{ {
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args); Dispose(clientStream, clientStreamReader, clientStreamWriter, args);
break; break;
} }
...@@ -397,7 +410,7 @@ namespace Titanium.Web.Proxy ...@@ -397,7 +410,7 @@ namespace Titanium.Web.Proxy
//if connection is closing exit //if connection is closing exit
if (args.WebSession.Response.ResponseKeepAlive == false) if (args.WebSession.Response.ResponseKeepAlive == false)
{ {
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args); Dispose(clientStream, clientStreamReader, clientStreamWriter, args);
break; break;
} }
...@@ -407,7 +420,7 @@ namespace Titanium.Web.Proxy ...@@ -407,7 +420,7 @@ namespace Titanium.Web.Proxy
} }
catch catch
{ {
Dispose(client, clientStream, clientStreamReader, clientStreamWriter, args); Dispose(clientStream, clientStreamReader, clientStreamWriter, args);
break; break;
} }
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Net.Sockets;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Compression; using Titanium.Web.Proxy.Compression;
...@@ -114,7 +112,7 @@ namespace Titanium.Web.Proxy ...@@ -114,7 +112,7 @@ namespace Titanium.Web.Proxy
} }
catch catch
{ {
Dispose(args.ProxyClient.TcpClient, args.ProxyClient.ClientStream, args.ProxyClient.ClientStreamReader, Dispose(args.ProxyClient.ClientStream, args.ProxyClient.ClientStreamReader,
args.ProxyClient.ClientStreamWriter, args); args.ProxyClient.ClientStreamWriter, args);
} }
finally finally
...@@ -216,32 +214,30 @@ namespace Titanium.Web.Proxy ...@@ -216,32 +214,30 @@ namespace Titanium.Web.Proxy
/// <param name="clientStreamReader"></param> /// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param> /// <param name="clientStreamWriter"></param>
/// <param name="args"></param> /// <param name="args"></param>
private void Dispose(TcpClient tcpClient, IDisposable clientStream, IDisposable clientStreamReader, private void Dispose(Stream clientStream, IDisposable clientStreamReader,
IDisposable clientStreamWriter, IDisposable args) IDisposable clientStreamWriter, IDisposable args)
{ {
if (clientStream != null) if (clientStream != null)
{ {
(clientStream as Stream).Close(); clientStream.Close();
(clientStream as Stream).Dispose(); clientStream.Dispose();
}
if (tcpClient != null)
{
tcpClient.Client.Close();
tcpClient.Close();
tcpClient.Client.Dispose();
} }
if (args != null) if (args != null)
{
args.Dispose(); args.Dispose();
}
if (clientStreamReader != null) if (clientStreamReader != null)
{
clientStreamReader.Dispose(); clientStreamReader.Dispose();
}
if (clientStreamWriter != null) if (clientStreamWriter != null)
{
clientStreamWriter.Dispose(); clientStreamWriter.Dispose();
}
} }
} }
} }
\ No newline at end of file
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