Commit b7a9c729 authored by justcoding121's avatar justcoding121

implement tcp server connection pool

parent ad1ab97f
...@@ -23,7 +23,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -23,7 +23,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
public ProxyTestController() public ProxyTestController()
{ {
proxyServer = new ProxyServer(); proxyServer = new ProxyServer();
proxyServer.EnableConnectionPool = true;
// generate root certificate without storing it in file system // generate root certificate without storing it in file system
//proxyServer.CertificateManager.CreateRootCertificate(false); //proxyServer.CertificateManager.CreateRootCertificate(false);
......
...@@ -140,7 +140,7 @@ namespace Titanium.Web.Proxy ...@@ -140,7 +140,7 @@ namespace Titanium.Web.Proxy
SslExtensions.Http2ProtocolAsList, cancellationToken); SslExtensions.Http2ProtocolAsList, cancellationToken);
http2Supproted = connection.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2; http2Supproted = connection.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2;
tcpConnectionFactory.Release(connection); tcpConnectionFactory.Release(connection, true);
} }
SslStream sslStream = null; SslStream sslStream = null;
...@@ -235,7 +235,7 @@ namespace Titanium.Web.Proxy ...@@ -235,7 +235,7 @@ namespace Titanium.Web.Proxy
(buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
connectArgs.CancellationTokenSource, ExceptionFunc); connectArgs.CancellationTokenSource, ExceptionFunc);
tcpConnectionFactory.Release(connection); tcpConnectionFactory.Release(connection, true);
return; return;
} }
} }
...@@ -280,7 +280,7 @@ namespace Titanium.Web.Proxy ...@@ -280,7 +280,7 @@ namespace Titanium.Web.Proxy
(buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc); connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc);
#endif #endif
tcpConnectionFactory.Release(connection); tcpConnectionFactory.Release(connection, true);
} }
} }
......
...@@ -216,6 +216,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -216,6 +216,9 @@ namespace Titanium.Web.Proxy.Http
ConnectRequest?.FinishSession(); ConnectRequest?.FinishSession();
Request?.FinishSession(); Request?.FinishSession();
Response?.FinishSession(); Response?.FinishSession();
Data.Clear();
UserData = null;
} }
} }
} }
...@@ -69,6 +69,15 @@ namespace Titanium.Web.Proxy.Models ...@@ -69,6 +69,15 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public int Port { get; set; } public int Port { get; set; }
/// <summary>
/// Get cache key for Tcp connection cahe.
/// </summary>
/// <returns></returns>
internal string GetCacheKey()
{
return $"{HostName}-{Port}" + (UseDefaultCredentials ? $"-{UserName}-{Password}" : string.Empty);
}
/// <summary> /// <summary>
/// returns data in Hostname:port format. /// returns data in Hostname:port format.
/// </summary> /// </summary>
......
...@@ -43,7 +43,6 @@ namespace Titanium.Web.Proxy.Network ...@@ -43,7 +43,6 @@ namespace Titanium.Web.Proxy.Network
/// </summary> /// </summary>
private readonly ConcurrentDictionary<string, CachedCertificate> certificateCache; private readonly ConcurrentDictionary<string, CachedCertificate> certificateCache;
private ExceptionHandler exceptionFunc;
private readonly ConcurrentDictionary<string, Task<X509Certificate2>> pendingCertificateCreationTasks; private readonly ConcurrentDictionary<string, Task<X509Certificate2>> pendingCertificateCreationTasks;
private ICertificateMaker certEngine; private ICertificateMaker certEngine;
...@@ -77,7 +76,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -77,7 +76,7 @@ namespace Titanium.Web.Proxy.Network
bool userTrustRootCertificate, bool machineTrustRootCertificate, bool trustRootCertificateAsAdmin, bool userTrustRootCertificate, bool machineTrustRootCertificate, bool trustRootCertificateAsAdmin,
ExceptionHandler exceptionFunc) ExceptionHandler exceptionFunc)
{ {
this.exceptionFunc = exceptionFunc; ExceptionFunc = exceptionFunc;
UserTrustRoot = userTrustRootCertificate || machineTrustRootCertificate; UserTrustRoot = userTrustRootCertificate || machineTrustRootCertificate;
...@@ -94,14 +93,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -94,14 +93,7 @@ namespace Titanium.Web.Proxy.Network
RootCertificateIssuerName = rootCertificateIssuerName; RootCertificateIssuerName = rootCertificateIssuerName;
} }
if (RunTime.IsWindows) CertificateEngine = RunTime.IsWindows ? CertificateEngine.DefaultWindows : CertificateEngine.BouncyCastle;
{
CertificateEngine = CertificateEngine.DefaultWindows;
}
else
{
CertificateEngine = CertificateEngine.BouncyCastle;
}
certificateCache = new ConcurrentDictionary<string, CachedCertificate>(); certificateCache = new ConcurrentDictionary<string, CachedCertificate>();
pendingCertificateCreationTasks = new ConcurrentDictionary<string, Task<X509Certificate2>>(); pendingCertificateCreationTasks = new ConcurrentDictionary<string, Task<X509Certificate2>>();
...@@ -131,6 +123,11 @@ namespace Titanium.Web.Proxy.Network ...@@ -131,6 +123,11 @@ namespace Titanium.Web.Proxy.Network
/// </summary> /// </summary>
internal bool TrustRootAsAdministrator { get; set; } internal bool TrustRootAsAdministrator { get; set; }
/// <summary>
/// Exception handler
/// </summary>
internal ExceptionHandler ExceptionFunc { get; set; }
/// <summary> /// <summary>
/// Select Certificate Engine. /// Select Certificate Engine.
/// Optionally set to BouncyCastle. /// Optionally set to BouncyCastle.
...@@ -156,8 +153,8 @@ namespace Titanium.Web.Proxy.Network ...@@ -156,8 +153,8 @@ namespace Titanium.Web.Proxy.Network
if (certEngine == null) if (certEngine == null)
{ {
certEngine = engine == CertificateEngine.BouncyCastle certEngine = engine == CertificateEngine.BouncyCastle
? (ICertificateMaker)new BCCertificateMaker(exceptionFunc) ? (ICertificateMaker)new BCCertificateMaker(ExceptionFunc)
: new WinCertificateMaker(exceptionFunc); : new WinCertificateMaker(ExceptionFunc);
} }
} }
} }
...@@ -235,10 +232,6 @@ namespace Titanium.Web.Proxy.Network ...@@ -235,10 +232,6 @@ namespace Titanium.Web.Proxy.Network
/// </summary> /// </summary>
public X509KeyStorageFlags StorageFlag { get; set; } = X509KeyStorageFlags.Exportable; public X509KeyStorageFlags StorageFlag { get; set; } = X509KeyStorageFlags.Exportable;
public ExceptionHandler ExceptionFunc {
set => exceptionFunc = value;
}
/// <summary> /// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary> /// </summary>
...@@ -329,7 +322,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -329,7 +322,7 @@ namespace Titanium.Web.Proxy.Network
{ {
if (RootCertificate == null) if (RootCertificate == null)
{ {
exceptionFunc(new Exception("Could not install certificate as it is null or empty.")); ExceptionFunc(new Exception("Could not install certificate as it is null or empty."));
return; return;
} }
...@@ -344,7 +337,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -344,7 +337,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc( ExceptionFunc(
new Exception("Failed to make system trust root certificate " new Exception("Failed to make system trust root certificate "
+ $" for {storeName}\\{storeLocation} store location. You may need admin rights.", + $" for {storeName}\\{storeLocation} store location. You may need admin rights.",
e)); e));
...@@ -366,7 +359,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -366,7 +359,7 @@ namespace Titanium.Web.Proxy.Network
{ {
if (certificate == null) if (certificate == null)
{ {
exceptionFunc(new Exception("Could not remove certificate as it is null or empty.")); ExceptionFunc(new Exception("Could not remove certificate as it is null or empty."));
return; return;
} }
...@@ -380,7 +373,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -380,7 +373,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc( ExceptionFunc(
new Exception("Failed to remove root certificate trust " new Exception("Failed to remove root certificate trust "
+ $" for {storeLocation} store location. You may need admin rights.", e)); + $" for {storeLocation} store location. You may need admin rights.", e));
} }
...@@ -438,7 +431,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -438,7 +431,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(new Exception("Failed to save fake certificate.", e)); ExceptionFunc(new Exception("Failed to save fake certificate.", e));
} }
}); });
} }
...@@ -462,7 +455,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -462,7 +455,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(e); ExceptionFunc(e);
} }
return certificate; return certificate;
...@@ -572,7 +565,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -572,7 +565,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(e); ExceptionFunc(e);
} }
if (persistToFile && RootCertificate != null) if (persistToFile && RootCertificate != null)
...@@ -593,7 +586,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -593,7 +586,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(e); ExceptionFunc(e);
} }
} }
...@@ -619,7 +612,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -619,7 +612,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(e); ExceptionFunc(e);
return null; return null;
} }
} }
...@@ -728,7 +721,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -728,7 +721,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(e); ExceptionFunc(e);
return false; return false;
} }
......
...@@ -48,6 +48,11 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -48,6 +48,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
private readonly TcpClient tcpClient; private readonly TcpClient tcpClient;
/// <summary>
/// The TcpClient.
/// </summary>
internal TcpClient TcpClient => tcpClient;
/// <summary> /// <summary>
/// Used to write lines to server /// Used to write lines to server
/// </summary> /// </summary>
...@@ -68,6 +73,11 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -68,6 +73,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary> /// </summary>
internal string CacheKey { get; set; } internal string CacheKey { get; set; }
/// <summary>
/// Is this connection authenticated via WinAuth
/// </summary>
internal bool IsWinAuthenticated { get; set; }
/// <summary> /// <summary>
/// Dispose. /// Dispose.
/// </summary> /// </summary>
......
...@@ -98,7 +98,7 @@ namespace Titanium.Web.Proxy ...@@ -98,7 +98,7 @@ namespace Titanium.Web.Proxy
ConnectionTimeOutSeconds = 60; ConnectionTimeOutSeconds = 60;
ProxyEndPoints = new List<ProxyEndPoint>(); ProxyEndPoints = new List<ProxyEndPoint>();
tcpConnectionFactory = new TcpConnectionFactory(); tcpConnectionFactory = new TcpConnectionFactory(ConnectionTimeOutSeconds);
if (!RunTime.IsRunningOnMono && RunTime.IsWindows) if (!RunTime.IsRunningOnMono && RunTime.IsWindows)
{ {
systemProxySettingsManager = new SystemProxyManager(); systemProxySettingsManager = new SystemProxyManager();
...@@ -149,6 +149,12 @@ namespace Titanium.Web.Proxy ...@@ -149,6 +149,12 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public bool Enable100ContinueBehaviour { get; set; } public bool Enable100ContinueBehaviour { get; set; }
/// <summary>
/// Should we enable experimental Tcp server connection pool?
/// Defaults to false.
/// </summary>
public bool EnableConnectionPool { get; set; }
/// <summary> /// <summary>
/// Buffer size used throughout this proxy. /// Buffer size used throughout this proxy.
/// </summary> /// </summary>
......
...@@ -55,6 +55,7 @@ namespace Titanium.Web.Proxy ...@@ -55,6 +55,7 @@ namespace Titanium.Web.Proxy
{ {
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
TcpServerConnection serverConnection = null; TcpServerConnection serverConnection = null;
bool serverConnectionClose = false;
try try
{ {
...@@ -182,7 +183,7 @@ namespace Titanium.Web.Proxy ...@@ -182,7 +183,7 @@ namespace Titanium.Web.Proxy
|| args.WebSession.UpStreamEndPoint?.Equals(serverConnection.UpStreamEndPoint) == || args.WebSession.UpStreamEndPoint?.Equals(serverConnection.UpStreamEndPoint) ==
false)) false))
{ {
serverConnection.Dispose(); tcpConnectionFactory.Release(serverConnection, true);
serverConnection = null; serverConnection = null;
} }
...@@ -241,6 +242,7 @@ namespace Titanium.Web.Proxy ...@@ -241,6 +242,7 @@ namespace Titanium.Web.Proxy
// if connection is closing exit // if connection is closing exit
if (!response.KeepAlive) if (!response.KeepAlive)
{ {
serverConnectionClose = true;
return; return;
} }
...@@ -257,6 +259,7 @@ namespace Titanium.Web.Proxy ...@@ -257,6 +259,7 @@ namespace Titanium.Web.Proxy
catch (Exception e) catch (Exception e)
{ {
args.Exception = e; args.Exception = e;
serverConnectionClose = true;
throw; throw;
} }
finally finally
...@@ -268,7 +271,7 @@ namespace Titanium.Web.Proxy ...@@ -268,7 +271,7 @@ namespace Titanium.Web.Proxy
} }
finally finally
{ {
tcpConnectionFactory.Release(serverConnection); tcpConnectionFactory.Release(serverConnection, serverConnectionClose || !EnableConnectionPool);
} }
} }
......
...@@ -89,7 +89,7 @@ namespace Titanium.Web.Proxy ...@@ -89,7 +89,7 @@ namespace Titanium.Web.Proxy
{ {
// create new connection // create new connection
var connection = await tcpConnectionFactory.GetClient(httpsHostName, endPoint.Port, var connection = await tcpConnectionFactory.GetClient(httpsHostName, endPoint.Port,
null, false, new List<SslApplicationProtocol> { clientConnection.NegotiatedApplicationProtocol }, null, false, null,
true, this, UpStreamEndPoint, UpStreamHttpsProxy, cancellationToken); true, this, UpStreamEndPoint, UpStreamHttpsProxy, cancellationToken);
...@@ -117,7 +117,7 @@ namespace Titanium.Web.Proxy ...@@ -117,7 +117,7 @@ namespace Titanium.Web.Proxy
await TcpHelper.SendRaw(clientStream, serverStream, BufferSize, await TcpHelper.SendRaw(clientStream, serverStream, BufferSize,
null, null, cancellationTokenSource, ExceptionFunc); null, null, cancellationTokenSource, ExceptionFunc);
tcpConnectionFactory.Release(connection); tcpConnectionFactory.Release(connection, true);
return; return;
} }
......
...@@ -145,6 +145,8 @@ namespace Titanium.Web.Proxy ...@@ -145,6 +145,8 @@ namespace Titanium.Web.Proxy
{ {
request.ContentLength = request.Body.Length; request.ContentLength = request.Body.Length;
} }
args.WebSession.ServerConnection.IsWinAuthenticated = true;
} }
// Need to revisit this. // Need to revisit this.
......
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