Commit 2284d1b2 authored by justcoding121's avatar justcoding121

implement tcp server connection pool

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